diff --git a/src/Microsoft.TestPlatform.Common/Hosting/ITestRuntimeProviderManager.cs b/src/Microsoft.TestPlatform.Common/Hosting/ITestRuntimeProviderManager.cs index d1073bc2ab..f57666d6f1 100644 --- a/src/Microsoft.TestPlatform.Common/Hosting/ITestRuntimeProviderManager.cs +++ b/src/Microsoft.TestPlatform.Common/Hosting/ITestRuntimeProviderManager.cs @@ -9,6 +9,6 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.Hosting; internal interface ITestRuntimeProviderManager { - ITestRuntimeProvider GetTestHostManagerByRunConfiguration(string runConfiguration, List sources); - ITestRuntimeProvider GetTestHostManagerByUri(string hostUri); + ITestRuntimeProvider? GetTestHostManagerByRunConfiguration(string? runConfiguration, List sources); + ITestRuntimeProvider? GetTestHostManagerByUri(string hostUri); } diff --git a/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeProviderManager.cs b/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeProviderManager.cs index d0cbf55fec..4090bdcfd6 100644 --- a/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeProviderManager.cs +++ b/src/Microsoft.TestPlatform.Common/Hosting/TestRunTimeProviderManager.cs @@ -8,8 +8,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.Common.Hosting; /// @@ -17,7 +15,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.Hosting; /// public class TestRuntimeProviderManager : ITestRuntimeProviderManager { - private static TestRuntimeProviderManager s_testHostManager; + private static TestRuntimeProviderManager? s_testHostManager; private readonly TestRuntimeExtensionManager _testHostExtensionManager; @@ -39,20 +37,20 @@ protected TestRuntimeProviderManager(IMessageLogger sessionLogger) public static TestRuntimeProviderManager Instance => s_testHostManager ??= new TestRuntimeProviderManager(TestSessionMessageLogger.Instance); - public ITestRuntimeProvider GetTestHostManagerByUri(string hostUri) + public ITestRuntimeProvider? GetTestHostManagerByUri(string hostUri) { var host = _testHostExtensionManager.TryGetTestExtension(hostUri); return host?.Value; } - public virtual ITestRuntimeProvider GetTestHostManagerByRunConfiguration(string runConfiguration, List _) + public virtual ITestRuntimeProvider? GetTestHostManagerByRunConfiguration(string? runConfiguration, List? _) { foreach (var testExtension in _testHostExtensionManager.TestExtensions) { if (testExtension.Value.CanExecuteCurrentRunConfiguration(runConfiguration)) { // we are creating a new Instance of ITestRuntimeProvider so that each POM gets it's own object of ITestRuntimeProvider - return (ITestRuntimeProvider)Activator.CreateInstance(testExtension.Value.GetType()); + return (ITestRuntimeProvider?)Activator.CreateInstance(testExtension.Value.GetType()); } } diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionRequestSender.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionRequestSender.cs index 55adf2f211..8f1a95c004 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionRequestSender.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionRequestSender.cs @@ -98,7 +98,7 @@ public void SendTestHostLaunched(TestHostLaunchedPayload testHostLaunchedPayload } /// - public BeforeTestRunStartResult? SendBeforeTestRunStartAndGetResult(string settingsXml, IEnumerable sources, bool isTelemetryOptedIn, ITestMessageEventHandler? runEventsHandler) + public BeforeTestRunStartResult? SendBeforeTestRunStartAndGetResult(string? settingsXml, IEnumerable sources, bool isTelemetryOptedIn, ITestMessageEventHandler? runEventsHandler) { var isDataCollectionStarted = false; BeforeTestRunStartResult? result = null; diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestDiscoveryEventHandler.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestDiscoveryEventHandler.cs index 73e5cd35e4..9b3792b07f 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestDiscoveryEventHandler.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestDiscoveryEventHandler.cs @@ -30,7 +30,7 @@ public TestDiscoveryEventHandler(ITestRequestHandler requestHandler) /// Handles discovered tests /// /// List of test cases - public void HandleDiscoveredTests(IEnumerable? discoveredTestCases) + public void HandleDiscoveredTests(IEnumerable discoveredTestCases) { EqtTrace.Info("Test Cases found "); _requestHandler.SendTestCases(discoveredTestCases); diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestRunEventsHandler.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestRunEventsHandler.cs index bde9f7a619..b15c28d16f 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestRunEventsHandler.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestRunEventsHandler.cs @@ -32,7 +32,7 @@ public TestRunEventsHandler(ITestRequestHandler requestHandler) /// Handle test run stats change. /// /// The test run changed args. - public void HandleTestRunStatsChange(TestRunChangedEventArgs? testRunChangedArgs) + public void HandleTestRunStatsChange(TestRunChangedEventArgs testRunChangedArgs) { EqtTrace.Info("Sending test run statistics"); _requestHandler.SendTestRunStatistics(testRunChangedArgs); @@ -45,7 +45,7 @@ public void HandleTestRunStatsChange(TestRunChangedEventArgs? testRunChangedArgs /// The last chunk args. /// The run context attachments. /// The executor uris. - public void HandleTestRunComplete(TestRunCompleteEventArgs? testRunCompleteArgs, TestRunChangedEventArgs? lastChunkArgs, ICollection? runContextAttachments, ICollection? executorUris) + public void HandleTestRunComplete(TestRunCompleteEventArgs testRunCompleteArgs, TestRunChangedEventArgs lastChunkArgs, ICollection runContextAttachments, ICollection executorUris) { EqtTrace.Info("Sending test run complete"); _requestHandler.SendExecutionComplete(testRunCompleteArgs, lastChunkArgs, runContextAttachments, executorUris); diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/Communication/ConnectedEventArgs.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/Communication/ConnectedEventArgs.cs index 362e918798..12c2de0dcc 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/Communication/ConnectedEventArgs.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/Communication/ConnectedEventArgs.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; @@ -42,6 +43,8 @@ public ConnectedEventArgs(Exception? faultException) /// /// Gets a value indicating whether channel is connected or not, true if it's connected. /// + [MemberNotNullWhen(true, nameof(Channel))] + [MemberNotNullWhen(false, nameof(Fault))] public bool Connected { get; private set; } /// diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/IDataCollectionRequestSender.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/IDataCollectionRequestSender.cs index 960e1ae741..f8e8869f94 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/IDataCollectionRequestSender.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/IDataCollectionRequestSender.cs @@ -58,7 +58,7 @@ internal interface IDataCollectionRequestSender /// /// BeforeTestRunStartResult containing environment variables /// - BeforeTestRunStartResult? SendBeforeTestRunStartAndGetResult(string settingXml, IEnumerable sources, bool isTelemetryOptedIn, ITestMessageEventHandler? runEventsHandler); + BeforeTestRunStartResult? SendBeforeTestRunStartAndGetResult(string? settingXml, IEnumerable sources, bool isTelemetryOptedIn, ITestMessageEventHandler? runEventsHandler); /// /// Sends the AfterTestRunEnd event and waits for result diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/IDataSerializer.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/IDataSerializer.cs index ce8696170f..468cf07a4c 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/IDataSerializer.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/IDataSerializer.cs @@ -21,7 +21,7 @@ public interface IDataSerializer /// The type of object to deserialize to. /// Message object /// TestPlatform object - T? DeserializePayload(Message message); + T? DeserializePayload(Message? message); /// /// Serializes and creates a raw message given a message type diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/ITestRequestHandler.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/ITestRequestHandler.cs index 58f43a5ab8..d64271926a 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/ITestRequestHandler.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/ITestRequestHandler.cs @@ -49,13 +49,13 @@ public interface ITestRequestHandler : IDisposable /// The send test cases. /// /// The discovered test cases. - void SendTestCases(IEnumerable? discoveredTestCases); + void SendTestCases(IEnumerable discoveredTestCases); /// /// The send test run statistics. /// /// The test run changed args. - void SendTestRunStatistics(TestRunChangedEventArgs? testRunChangedArgs); + void SendTestRunStatistics(TestRunChangedEventArgs testRunChangedArgs); /// /// Sends the logs back to the server. @@ -71,7 +71,7 @@ public interface ITestRequestHandler : IDisposable /// The last chunk args. /// The run context attachments. /// The executor uris. - void SendExecutionComplete(TestRunCompleteEventArgs? testRunCompleteArgs, TestRunChangedEventArgs? lastChunkArgs, ICollection? runContextAttachments, ICollection? executorUris); + void SendExecutionComplete(TestRunCompleteEventArgs testRunCompleteArgs, TestRunChangedEventArgs lastChunkArgs, ICollection runContextAttachments, ICollection executorUris); /// /// The discovery complete handler diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/JsonDataSerializer.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/JsonDataSerializer.cs index 4794071dc1..bc140ce8bc 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/JsonDataSerializer.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/JsonDataSerializer.cs @@ -126,8 +126,13 @@ public Message DeserializeMessage(string rawMessage) /// A object. /// Payload type. /// The deserialized payload. - public T? DeserializePayload(Message message) + public T? DeserializePayload(Message? message) { + if (message is null) + { + return default; + } + if (message.GetType() == typeof(Message)) { // Message is specifically a Message, and not any of it's child types like VersionedMessage. diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/ObjectModel/TestRunCriteriaWithSources.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/ObjectModel/TestRunCriteriaWithSources.cs index 8acd93afa3..6625842ae9 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/ObjectModel/TestRunCriteriaWithSources.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/ObjectModel/TestRunCriteriaWithSources.cs @@ -24,7 +24,7 @@ public class TestRunCriteriaWithSources /// The run settings. /// The test Execution Context. [JsonConstructor] - public TestRunCriteriaWithSources(Dictionary> adapterSourceMap, string package, string? runSettings, TestExecutionContext? testExecutionContext) + public TestRunCriteriaWithSources(Dictionary> adapterSourceMap, string? package, string? runSettings, TestExecutionContext? testExecutionContext) { AdapterSourceMap = adapterSourceMap; Package = package; @@ -50,5 +50,5 @@ public TestRunCriteriaWithSources(Dictionary> adapte /// /// Gets the test Containers (e.g. .appx, .appxrecipie) /// - public string Package { get; private set; } + public string? Package { get; private set; } } diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/ObjectModel/TestRunCriteriaWithTests.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/ObjectModel/TestRunCriteriaWithTests.cs index 2d5cb218ac..069ee9566c 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/ObjectModel/TestRunCriteriaWithTests.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/ObjectModel/TestRunCriteriaWithTests.cs @@ -26,7 +26,7 @@ public class TestRunCriteriaWithTests /// The test run settings. /// The test Execution Context. [JsonConstructor] - public TestRunCriteriaWithTests(IEnumerable tests, string package, string? runSettings, TestExecutionContext? testExecutionContext) + public TestRunCriteriaWithTests(IEnumerable tests, string? package, string? runSettings, TestExecutionContext? testExecutionContext) { Tests = tests; Package = package; @@ -52,5 +52,5 @@ public TestRunCriteriaWithTests(IEnumerable tests, string package, str /// /// Gets the test Containers (e.g. .appx, .appxrecipie) /// - public string Package { get; private set; } + public string? Package { get; private set; } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/FrameworkHandle.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/FrameworkHandle.cs index 9e19a7c39c..6a86c8c549 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/FrameworkHandle.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/FrameworkHandle.cs @@ -15,8 +15,6 @@ using CrossPlatEngineResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Adapter; /// @@ -47,7 +45,7 @@ internal class FrameworkHandle : TestExecutionRecorder, IFrameworkHandle2, IDisp /// The test run cache. /// The test execution context. /// TestRun Events Handler - public FrameworkHandle(ITestCaseEventsHandler testCaseEventsHandler, ITestRunCache testRunCache, + public FrameworkHandle(ITestCaseEventsHandler? testCaseEventsHandler, ITestRunCache testRunCache, TestExecutionContext testExecutionContext, IInternalTestRunEventsHandler testRunEventsHandler) : base(testCaseEventsHandler, testRunCache) { @@ -71,7 +69,7 @@ public FrameworkHandle(ITestCaseEventsHandler testCaseEventsHandler, ITestRunCac /// Command line arguments the process should be launched with. /// Environment variables to be set in target process /// Process ID of the started process. - public int LaunchProcessWithDebuggerAttached(string filePath, string workingDirectory, string arguments, IDictionary environmentVariables) + public int LaunchProcessWithDebuggerAttached(string filePath, string? workingDirectory, string? arguments, IDictionary? environmentVariables) { // If an adapter attempts to launch a process after the run is complete (=> this object is disposed) // throw an error. @@ -86,7 +84,7 @@ public int LaunchProcessWithDebuggerAttached(string filePath, string workingDire throw new InvalidOperationException(CrossPlatEngineResources.LaunchDebugProcessNotAllowedForANonDebugRun); } - var processInfo = new TestProcessStartInfo() + var processInfo = new TestProcessStartInfo { Arguments = arguments, EnvironmentVariables = environmentVariables, diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/RunContext.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/RunContext.cs index 7c12af2a11..6ea55760fc 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/RunContext.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/RunContext.cs @@ -2,15 +2,12 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Discovery; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Adapter; /// -/// Provides user specified runSettings and framework provided context of the run. +/// Provides user specified runSettings and framework provided context of the run. /// public class RunContext : DiscoveryContext, IRunContext { @@ -30,17 +27,17 @@ public class RunContext : DiscoveryContext, IRunContext public bool IsDataCollectionEnabled { get; internal set; } /// - /// Gets a value indicating whether the test is being debugged. + /// Gets a value indicating whether the test is being debugged. /// public bool IsBeingDebugged { get; internal set; } /// /// Gets the directory which should be used for storing result files/deployment files etc. /// - public string TestRunDirectory { get; internal set; } + public string? TestRunDirectory { get; internal set; } /// /// Gets the directory for Solution. /// - public string SolutionDirectory { get; internal set; } + public string? SolutionDirectory { get; internal set; } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/TestExecutionRecorder.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/TestExecutionRecorder.cs index 9f2e52bccc..6ae681e5d5 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/TestExecutionRecorder.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Adapter/TestExecutionRecorder.cs @@ -11,8 +11,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Adapter; /// @@ -22,7 +20,7 @@ internal class TestExecutionRecorder : TestSessionMessageLogger, ITestExecutionR { private readonly List _attachmentSets; private readonly ITestRunCache _testRunCache; - private readonly ITestCaseEventsHandler _testCaseEventsHandler; + private readonly ITestCaseEventsHandler? _testCaseEventsHandler; /// /// Contains TestCase Ids for test cases that are in progress @@ -37,7 +35,7 @@ internal class TestExecutionRecorder : TestSessionMessageLogger, ITestExecutionR /// /// The test Case Events Handler. /// The test run cache. - public TestExecutionRecorder(ITestCaseEventsHandler testCaseEventsHandler, ITestRunCache testRunCache) + public TestExecutionRecorder(ITestCaseEventsHandler? testCaseEventsHandler, ITestRunCache testRunCache) { _testRunCache = testRunCache; _testCaseEventsHandler = testCaseEventsHandler; @@ -70,7 +68,7 @@ internal Collection Attachments /// test case which will be started. public void RecordStart(TestCase testCase) { - EqtTrace.Verbose("TestExecutionRecorder.RecordStart: Starting test: {0}.", testCase?.FullyQualifiedName); + EqtTrace.Verbose("TestExecutionRecorder.RecordStart: Starting test: {0}.", testCase.FullyQualifiedName); _testRunCache.OnTestStarted(testCase); if (_testCaseEventsHandler != null) @@ -95,7 +93,7 @@ public void RecordStart(TestCase testCase) /// test result to the framework when the test(s) is canceled. public void RecordResult(TestResult testResult) { - EqtTrace.Verbose("TestExecutionRecorder.RecordResult: Received result for test: {0}.", testResult?.TestCase?.FullyQualifiedName); + EqtTrace.Verbose("TestExecutionRecorder.RecordResult: Received result for test: {0}.", testResult.TestCase.FullyQualifiedName); if (_testCaseEventsHandler != null) { // Send TestCaseEnd in case RecordEnd was not called. @@ -109,13 +107,13 @@ public void RecordResult(TestResult testResult) /// /// Notify the framework about completion of the test case. - /// Framework sends this event to data collectors enabled in the run. If no data collector is enabled, then the event is ignored. + /// Framework sends this event to data collectors enabled in the run. If no data collector is enabled, then the event is ignored. /// /// test case which has completed. /// outcome of the test case. public void RecordEnd(TestCase testCase, TestOutcome outcome) { - EqtTrace.Verbose("TestExecutionRecorder.RecordEnd: test: {0} execution completed.", testCase?.FullyQualifiedName); + EqtTrace.Verbose("TestExecutionRecorder.RecordEnd: test: {0} execution completed.", testCase.FullyQualifiedName); _testRunCache.OnTestCompletion(testCase); SendTestCaseEnd(testCase, outcome); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentProcessorAppDomain.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentProcessorAppDomain.cs index e635a51ff9..4c78f33fb9 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentProcessorAppDomain.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentProcessorAppDomain.cs @@ -51,7 +51,7 @@ internal class DataCollectorAttachmentProcessorAppDomain : IDataCollectorAttachm private IMessageLogger? _processAttachmentSetsLogger; private IProgress? _progressReporter; - public DataCollectorAttachmentProcessorAppDomain(InvokedDataCollector invokedDataCollector, IMessageLogger dataCollectorAttachmentsProcessorsLogger) + public DataCollectorAttachmentProcessorAppDomain(InvokedDataCollector invokedDataCollector, IMessageLogger? dataCollectorAttachmentsProcessorsLogger) { _invokedDataCollector = invokedDataCollector ?? throw new ArgumentNullException(nameof(invokedDataCollector)); _appDomain = AppDomain.CreateDomain(invokedDataCollector.Uri.ToString()); diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentsProcessorsFactory.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentsProcessorsFactory.cs index 054638db11..c357c555bc 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentsProcessorsFactory.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentsProcessorsFactory.cs @@ -16,8 +16,6 @@ using Microsoft.VisualStudio.TestPlatform.Utilities; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing; internal class DataCollectorAttachmentsProcessorsFactory : IDataCollectorAttachmentsProcessorsFactory @@ -25,7 +23,7 @@ internal class DataCollectorAttachmentsProcessorsFactory : IDataCollectorAttachm private const string CoverageFriendlyName = "Code Coverage"; private static readonly ConcurrentDictionary DataCollectorExtensionManagerCache = new(); - public DataCollectorAttachmentProcessor[] Create(InvokedDataCollector[] invokedDataCollectors, IMessageLogger logger) + public DataCollectorAttachmentProcessor[] Create(InvokedDataCollector[]? invokedDataCollectors, IMessageLogger? logger) { IDictionary> datacollectorsAttachmentsProcessors = new Dictionary>(); @@ -62,9 +60,9 @@ public DataCollectorAttachmentProcessor[] Create(InvokedDataCollector[] invokedD var wrapper = new DataCollectorAttachmentProcessorAppDomain(invokedDataCollector, logger); if (wrapper.LoadSucceded && wrapper.HasAttachmentProcessor) { - if (!datacollectorsAttachmentsProcessors.ContainsKey(wrapper.AssemblyQualifiedName)) + if (!datacollectorsAttachmentsProcessors.ContainsKey(wrapper.AssemblyQualifiedName!)) { - datacollectorsAttachmentsProcessors.Add(wrapper.AssemblyQualifiedName, new Tuple(wrapper.FriendlyName, wrapper)); + datacollectorsAttachmentsProcessors.Add(wrapper.AssemblyQualifiedName!, new Tuple(wrapper.FriendlyName!, wrapper)); EqtTrace.Info($"DataCollectorAttachmentsProcessorsFactory: Collector attachment processor '{wrapper.AssemblyQualifiedName}' from file '{invokedDataCollector.FilePath}' added to the 'run list'"); } else @@ -94,7 +92,7 @@ public DataCollectorAttachmentProcessor[] Create(InvokedDataCollector[] invokedD if (dataCollectorExtension?.Metadata.HasAttachmentProcessor == true) { Type attachmentProcessorType = ((DataCollectorConfig)dataCollectorExtension.TestPluginInfo).AttachmentsProcessorType; - IDataCollectorAttachmentProcessor dataCollectorAttachmentProcessorInstance = null; + IDataCollectorAttachmentProcessor? dataCollectorAttachmentProcessorInstance = null; try { dataCollectorAttachmentProcessorInstance = TestPluginManager.CreateTestExtension(attachmentProcessorType); @@ -106,9 +104,11 @@ public DataCollectorAttachmentProcessor[] Create(InvokedDataCollector[] invokedD logger?.SendMessage(TestMessageLevel.Error, $"DataCollectorAttachmentsProcessorsFactory: Failed during the creation of data collector attachment processor '{attachmentProcessorType.AssemblyQualifiedName}'\n{ex}"); } - if (dataCollectorAttachmentProcessorInstance is not null && !datacollectorsAttachmentsProcessors.ContainsKey(attachmentProcessorType.AssemblyQualifiedName)) + var attachmentQualifiedName = attachmentProcessorType.AssemblyQualifiedName; + TPDebug.Assert(attachmentQualifiedName is not null, "attachmentQualifiedName is null"); + if (dataCollectorAttachmentProcessorInstance is not null && !datacollectorsAttachmentsProcessors.ContainsKey(attachmentQualifiedName)) { - datacollectorsAttachmentsProcessors.Add(attachmentProcessorType.AssemblyQualifiedName, new Tuple(dataCollectorExtension.Metadata.FriendlyName, dataCollectorAttachmentProcessorInstance)); + datacollectorsAttachmentsProcessors.Add(attachmentQualifiedName, new Tuple(dataCollectorExtension.Metadata.FriendlyName, dataCollectorAttachmentProcessorInstance)); EqtTrace.Info($"DataCollectorAttachmentsProcessorsFactory: Collector attachment processor '{attachmentProcessorType.AssemblyQualifiedName}' from file '{invokedDataCollector.FilePath}' added to the 'run list'"); } } @@ -122,9 +122,9 @@ public DataCollectorAttachmentProcessor[] Create(InvokedDataCollector[] invokedD // We provide the implementation of CodeCoverageDataAttachmentsHandler through nuget package, but in case of absent registration or if for some reason // the attachment processor from package fails we fallback to the default implementation. - if (!datacollectorsAttachmentsProcessors.ContainsKey(typeof(CodeCoverageDataAttachmentsHandler).AssemblyQualifiedName)) + if (!datacollectorsAttachmentsProcessors.ContainsKey(typeof(CodeCoverageDataAttachmentsHandler).AssemblyQualifiedName!)) { - datacollectorsAttachmentsProcessors.Add(typeof(CodeCoverageDataAttachmentsHandler).AssemblyQualifiedName, new Tuple(CoverageFriendlyName, new CodeCoverageDataAttachmentsHandler())); + datacollectorsAttachmentsProcessors.Add(typeof(CodeCoverageDataAttachmentsHandler).AssemblyQualifiedName!, new Tuple(CoverageFriendlyName, new CodeCoverageDataAttachmentsHandler())); EqtTrace.Info($"DataCollectorAttachmentsProcessorsFactory: Collector attachment processor '{typeof(CodeCoverageDataAttachmentsHandler).AssemblyQualifiedName}' for the data collector with friendly name '{CoverageFriendlyName}' added to the 'run list'"); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/TestRunAttachmentsProcessingManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/TestRunAttachmentsProcessingManager.cs index 1d42fbd6a8..70e4676403 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/TestRunAttachmentsProcessingManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/TestRunAttachmentsProcessingManager.cs @@ -18,12 +18,10 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing; /// -/// Orchestrates test run attachments processing operations. +/// Orchestrates test run localAttachments processing operations. /// internal class TestRunAttachmentsProcessingManager : ITestRunAttachmentsProcessingManager { @@ -44,31 +42,32 @@ public TestRunAttachmentsProcessingManager(ITestPlatformEventSource testPlatform } /// - public async Task ProcessTestRunAttachmentsAsync(string runSettingsXml, IRequestData requestData, IEnumerable attachments, IEnumerable invokedDataCollector, ITestRunAttachmentsProcessingEventsHandler eventHandler, CancellationToken cancellationToken) + public async Task ProcessTestRunAttachmentsAsync(string? runSettingsXml, IRequestData requestData, IEnumerable attachments, IEnumerable invokedDataCollector, ITestRunAttachmentsProcessingEventsHandler eventHandler, CancellationToken cancellationToken) { - await InternalProcessTestRunAttachmentsAsync(runSettingsXml, requestData, new Collection(attachments.ToList()), invokedDataCollector, eventHandler, cancellationToken).ConfigureAwait(false); + await InternalProcessTestRunAttachmentsAsync(runSettingsXml, requestData, attachments, invokedDataCollector, eventHandler, cancellationToken).ConfigureAwait(false); } /// - public Task> ProcessTestRunAttachmentsAsync(string runSettingsXml, IRequestData requestData, IEnumerable attachments, IEnumerable invokedDataCollector, CancellationToken cancellationToken) + public Task> ProcessTestRunAttachmentsAsync(string? runSettingsXml, IRequestData requestData, IEnumerable attachments, IEnumerable invokedDataCollector, CancellationToken cancellationToken) { - return InternalProcessTestRunAttachmentsAsync(runSettingsXml, requestData, new Collection(attachments.ToList()), invokedDataCollector, null, cancellationToken); + return InternalProcessTestRunAttachmentsAsync(runSettingsXml, requestData, attachments, invokedDataCollector, null, cancellationToken); } - private async Task> InternalProcessTestRunAttachmentsAsync(string runSettingsXml, IRequestData requestData, Collection attachments, IEnumerable invokedDataCollector, ITestRunAttachmentsProcessingEventsHandler eventHandler, CancellationToken cancellationToken) + private async Task> InternalProcessTestRunAttachmentsAsync(string? runSettingsXml, IRequestData requestData, IEnumerable attachments, IEnumerable invokedDataCollector, ITestRunAttachmentsProcessingEventsHandler? eventHandler, CancellationToken cancellationToken) { var stopwatch = Stopwatch.StartNew(); + Collection localAttachments = new(attachments.ToList()); try { - _testPlatformEventSource.TestRunAttachmentsProcessingStart(attachments?.Count ?? 0); - requestData.MetricsCollection.Add(TelemetryDataConstants.NumberOfAttachmentsSentForProcessing, attachments?.Count ?? 0); + _testPlatformEventSource.TestRunAttachmentsProcessingStart(localAttachments.Count); + requestData.MetricsCollection.Add(TelemetryDataConstants.NumberOfAttachmentsSentForProcessing, localAttachments.Count); cancellationToken.ThrowIfCancellationRequested(); var cancelAttachmentProcessingCompletionSource = new TaskCompletionSource>(); using (cancellationToken.Register(() => cancelAttachmentProcessingCompletionSource.TrySetCanceled())) { - Task> task = Task.Run(async () => await ProcessAttachmentsAsync(runSettingsXml, new Collection(attachments.ToList()), invokedDataCollector, eventHandler, cancellationToken)); + Task> task = Task.Run(async () => await ProcessAttachmentsAsync(runSettingsXml, localAttachments, invokedDataCollector, eventHandler, cancellationToken)); var completedTask = await Task.WhenAny(task, cancelAttachmentProcessingCompletionSource.Task).ConfigureAwait(false); @@ -79,7 +78,7 @@ private async Task> InternalProcessTestRunAttachmentsA else { eventHandler?.HandleLogMessage(TestMessageLevel.Informational, "Attachments processing was cancelled."); - return FinalizeOperation(requestData, new TestRunAttachmentsProcessingCompleteEventArgs(true, null), attachments, stopwatch, eventHandler); + return FinalizeOperation(requestData, new TestRunAttachmentsProcessingCompleteEventArgs(true, null), localAttachments, stopwatch, eventHandler); } } } @@ -93,20 +92,26 @@ private async Task> InternalProcessTestRunAttachmentsA } EqtTrace.Warning("TestRunAttachmentsProcessingManager: Operation was cancelled."); - return FinalizeOperation(requestData, new TestRunAttachmentsProcessingCompleteEventArgs(true, null), attachments, stopwatch, eventHandler); + return FinalizeOperation(requestData, new TestRunAttachmentsProcessingCompleteEventArgs(true, null), localAttachments, stopwatch, eventHandler); } catch (Exception e) { EqtTrace.Error("TestRunAttachmentsProcessingManager: Exception in ProcessTestRunAttachmentsAsync: " + e); eventHandler?.HandleLogMessage(TestMessageLevel.Error, e.ToString()); - return FinalizeOperation(requestData, new TestRunAttachmentsProcessingCompleteEventArgs(false, e), attachments, stopwatch, eventHandler); + return FinalizeOperation(requestData, new TestRunAttachmentsProcessingCompleteEventArgs(false, e), localAttachments, stopwatch, eventHandler); } } - private async Task> ProcessAttachmentsAsync(string runSettingsXml, Collection attachments, IEnumerable invokedDataCollector, ITestRunAttachmentsProcessingEventsHandler eventsHandler, CancellationToken cancellationToken) + private async Task> ProcessAttachmentsAsync(string? runSettingsXml, Collection attachments, IEnumerable invokedDataCollector, ITestRunAttachmentsProcessingEventsHandler? eventsHandler, CancellationToken cancellationToken) { - if (attachments == null || !attachments.Any()) return attachments; + if (attachments.Count == 0) + { + return attachments; + } + + // Create a local copy of the collection to avoid modifying original one. + attachments = new(attachments.ToList()); var dataCollectionRunSettings = XmlRunSettingsUtilities.GetDataCollectionRunSettings(runSettingsXml); var logger = CreateMessageLogger(eventsHandler); @@ -126,51 +131,55 @@ private async Task> ProcessAttachmentsAsync(string run } // We run processor code inside a try/catch because we want to continue with the others in case of failure. - Collection attachmentsBackup = null; + Collection attachmentsBackup = null!; try { - // We temporarily save the attachments to process because, in case of processor exception, + // We temporarily save the localAttachments to process because, in case of processor exception, // we'll restore the attachmentSets to make those available to other processors. - // NB. attachments.ToList() is done on purpose we need a new ref list. + // NB. localAttachments.ToList() is done on purpose we need a new ref list. attachmentsBackup = new Collection(attachments.ToList()); - ICollection attachmentProcessorUris = dataCollectorAttachmentsProcessor.DataCollectorAttachmentProcessorInstance.GetExtensionUris()?.ToList(); - if (attachmentProcessorUris != null && attachmentProcessorUris.Any()) + ICollection? attachmentProcessorUris = dataCollectorAttachmentsProcessor.DataCollectorAttachmentProcessorInstance.GetExtensionUris()?.ToList(); + if (attachmentProcessorUris == null || attachmentProcessorUris.Count == 0) + { + continue; + } + + var attachmentsToBeProcessed = attachments.Where(dataCollectionAttachment => attachmentProcessorUris.Any(uri => uri.Equals(dataCollectionAttachment.Uri))).ToArray(); + if (attachmentsToBeProcessed.Length == 0) + { + continue; + } + + foreach (var attachment in attachmentsToBeProcessed) { - var attachmentsToBeProcessed = attachments.Where(dataCollectionAttachment => attachmentProcessorUris.Any(uri => uri.Equals(dataCollectionAttachment.Uri))).ToArray(); - if (attachmentsToBeProcessed.Any()) + attachments.Remove(attachment); + } + + IProgress progressReporter = new Progress((int progress) => + eventsHandler?.HandleTestRunAttachmentsProcessingProgress( + new TestRunAttachmentsProcessingProgressEventArgs(attachmentsHandlerIndex, attachmentProcessorUris, progress, dataCollectorAttachmentsProcessors.Length))); + + XmlElement? configuration = null; + var collectorConfiguration = dataCollectionRunSettings?.DataCollectorSettingsList.SingleOrDefault(c => c.FriendlyName == dataCollectorAttachmentsProcessor.FriendlyName); + if (collectorConfiguration != null && collectorConfiguration.IsEnabled) + { + configuration = collectorConfiguration.Configuration; + } + + EqtTrace.Info($"TestRunAttachmentsProcessingManager: Invocation of data collector attachment processor AssemblyQualifiedName: '{dataCollectorAttachmentsProcessor.DataCollectorAttachmentProcessorInstance.GetType().AssemblyQualifiedName}' FriendlyName: '{dataCollectorAttachmentsProcessor.FriendlyName}' with configuration '{(configuration == null ? "null" : configuration.OuterXml)}'"); + ICollection processedAttachments = await dataCollectorAttachmentsProcessor.DataCollectorAttachmentProcessorInstance.ProcessAttachmentSetsAsync( + configuration, + new Collection(attachmentsToBeProcessed), + progressReporter, + logger, + cancellationToken).ConfigureAwait(false); + + if (processedAttachments != null && processedAttachments.Count > 0) + { + foreach (var attachment in processedAttachments) { - foreach (var attachment in attachmentsToBeProcessed) - { - attachments.Remove(attachment); - } - - IProgress progressReporter = new Progress((int progress) => - eventsHandler?.HandleTestRunAttachmentsProcessingProgress( - new TestRunAttachmentsProcessingProgressEventArgs(attachmentsHandlerIndex, attachmentProcessorUris, progress, dataCollectorAttachmentsProcessors.Length))); - - XmlElement configuration = null; - var collectorConfiguration = dataCollectionRunSettings?.DataCollectorSettingsList.SingleOrDefault(c => c.FriendlyName == dataCollectorAttachmentsProcessor.FriendlyName); - if (collectorConfiguration != null && collectorConfiguration.IsEnabled) - { - configuration = collectorConfiguration.Configuration; - } - - EqtTrace.Info($"TestRunAttachmentsProcessingManager: Invocation of data collector attachment processor AssemblyQualifiedName: '{dataCollectorAttachmentsProcessor.DataCollectorAttachmentProcessorInstance.GetType().AssemblyQualifiedName}' FriendlyName: '{dataCollectorAttachmentsProcessor.FriendlyName}' with configuration '{(configuration == null ? "null" : configuration.OuterXml)}'"); - ICollection processedAttachments = await dataCollectorAttachmentsProcessor.DataCollectorAttachmentProcessorInstance.ProcessAttachmentSetsAsync( - configuration, - new Collection(attachmentsToBeProcessed), - progressReporter, - logger, - cancellationToken).ConfigureAwait(false); - - if (processedAttachments != null && processedAttachments.Any()) - { - foreach (var attachment in processedAttachments) - { - attachments.Add(attachment); - } - } + attachments.Add(attachment); } } } @@ -194,7 +203,7 @@ private async Task> ProcessAttachmentsAsync(string run return attachments; } - private Collection FinalizeOperation(IRequestData requestData, TestRunAttachmentsProcessingCompleteEventArgs completeArgs, Collection attachments, Stopwatch stopwatch, ITestRunAttachmentsProcessingEventsHandler eventHandler) + private Collection FinalizeOperation(IRequestData requestData, TestRunAttachmentsProcessingCompleteEventArgs completeArgs, Collection attachments, Stopwatch stopwatch, ITestRunAttachmentsProcessingEventsHandler? eventHandler) { _testPlatformEventSource.TestRunAttachmentsProcessingStop(attachments.Count); requestData.MetricsCollection.Add(TelemetryDataConstants.NumberOfAttachmentsAfterProcessing, attachments.Count); @@ -209,10 +218,10 @@ private Collection FinalizeOperation(IRequestData requestData, Te return attachments; } - private IMessageLogger CreateMessageLogger(ITestRunAttachmentsProcessingEventsHandler eventsHandler) - { - return eventsHandler != null ? (IMessageLogger)new AttachmentsProcessingMessageLogger(eventsHandler) : new NullMessageLogger(); - } + private static IMessageLogger CreateMessageLogger(ITestRunAttachmentsProcessingEventsHandler? eventsHandler) + => eventsHandler != null + ? new AttachmentsProcessingMessageLogger(eventsHandler) + : new NullMessageLogger(); private class AttachmentsProcessingMessageLogger : IMessageLogger { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/DiscoveryCriteriaExtensions.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/DiscoveryCriteriaExtensions.cs index d110f19b19..ed91c5190d 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/DiscoveryCriteriaExtensions.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/DiscoveryCriteriaExtensions.cs @@ -7,8 +7,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; internal static class DiscoveryCriteriaExtensions diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyDiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyDiscoveryManager.cs index 44fc1f7fc0..b61c129ce9 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyDiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyDiscoveryManager.cs @@ -14,8 +14,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; internal class InProcessProxyDiscoveryManager : IProxyDiscoveryManager diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyexecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyexecutionManager.cs index fc40a74b13..cb593fc15f 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyexecutionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyexecutionManager.cs @@ -17,8 +17,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; internal class InProcessProxyExecutionManager : IProxyExecutionManager diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/LoggerNameValueConfigurationManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/LoggerNameValueConfigurationManager.cs index b9c97df06d..4237430e62 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/LoggerNameValueConfigurationManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/LoggerNameValueConfigurationManager.cs @@ -6,8 +6,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// @@ -28,7 +26,7 @@ public LoggerNameValueConfigurationManager(XmlElement configurationElement) Initialize(configurationElement); } - public Dictionary NameValuePairs { get; } = new Dictionary(); + public Dictionary NameValuePairs { get; } = new(); private void Initialize(XmlElement configurationElement) { @@ -54,7 +52,7 @@ private void Initialize(XmlElement configurationElement) // Get the setting value string settingValue = settingElement.InnerText; - if (string.IsNullOrWhiteSpace(settingValue)) + if (settingValue.IsNullOrWhiteSpace()) { EqtTrace.Warning("Skipping configuration setting '{0}' due to missing value", settingName); continue; diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/DiscoveryDataAggregator.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/DiscoveryDataAggregator.cs index e087f83017..efa87b2e94 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/DiscoveryDataAggregator.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/DiscoveryDataAggregator.cs @@ -143,7 +143,7 @@ public void AggregateMetrics(IDictionary? metrics) { var newValue = Convert.ToDouble(metric.Value); - if (_metricsAggregator.TryGetValue(metric.Key, out object oldValue)) + if (_metricsAggregator.TryGetValue(metric.Key, out object? oldValue)) { double oldDoubleValue = Convert.ToDouble(oldValue); _metricsAggregator[metric.Key] = newValue + oldDoubleValue; diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyDiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyDiscoveryManager.cs index 1d46f668a4..692efcdc14 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyDiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyDiscoveryManager.cs @@ -84,7 +84,7 @@ public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEve var workloads = SplitToWorkloads(discoveryCriteria, _sourceToTestHostProviderMap); _availableTestSources = workloads.SelectMany(w => w.Work.Sources).Count(); var runnableWorkloads = workloads.Where(workload => workload.HasProvider).ToList(); - _availableWorkloads = runnableWorkloads.Count(); + _availableWorkloads = runnableWorkloads.Count; var nonRunnableWorkloads = workloads.Where(workload => !workload.HasProvider).ToList(); EqtTrace.Verbose("ParallelProxyDiscoveryManager.DiscoverTests: Start discovery. Total sources: " + _availableTestSources); @@ -230,8 +230,7 @@ private List> SplitToWorkloads(Disco foreach (var sourcesToDiscover in sourceBatches) { - var runsettings = testhostProviderInfo.RunSettings; - var updatedCriteria = NewDiscoveryCriteriaFromSourceAndSettings(sourcesToDiscover, discoveryCriteria, runsettings); + var updatedCriteria = NewDiscoveryCriteriaFromSourceAndSettings(sourcesToDiscover, discoveryCriteria, testhostProviderInfo.RunSettings); var workload = new ProviderSpecificWorkload(updatedCriteria, testhostProviderInfo); workloads.Add(workload); } @@ -239,7 +238,7 @@ private List> SplitToWorkloads(Disco return workloads; - static DiscoveryCriteria NewDiscoveryCriteriaFromSourceAndSettings(IEnumerable sources, DiscoveryCriteria discoveryCriteria, string runsettingsXml) + static DiscoveryCriteria NewDiscoveryCriteriaFromSourceAndSettings(IEnumerable sources, DiscoveryCriteria discoveryCriteria, string? runsettingsXml) { var criteria = new DiscoveryCriteria( sources, @@ -278,9 +277,10 @@ private void DiscoverTestsOnConcurrentManager(IProxyDiscoveryManager proxyDiscov EqtTrace.Error("ParallelProxyDiscoveryManager: Failed to trigger discovery. Exception: " + t.Exception); var handler = eventHandler; - var testMessagePayload = new TestMessagePayload { MessageLevel = TestMessageLevel.Error, Message = t.Exception.ToString() }; + var exceptionToString = t.Exception?.ToString(); + var testMessagePayload = new TestMessagePayload { MessageLevel = TestMessageLevel.Error, Message = exceptionToString }; handler.HandleRawMessage(_dataSerializer.SerializePayload(MessageType.TestMessage, testMessagePayload)); - handler.HandleLogMessage(TestMessageLevel.Error, t.Exception.ToString()); + handler.HandleLogMessage(TestMessageLevel.Error, exceptionToString); // Send discovery complete. Similar logic is also used in ProxyDiscoveryManager.DiscoverTests. // Differences: diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyExecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyExecutionManager.cs index 33b907059e..fb6793a45b 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyExecutionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyExecutionManager.cs @@ -19,8 +19,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client.Parallel; /// @@ -42,7 +40,7 @@ internal class ParallelProxyExecutionManager : IParallelProxyExecutionManager private int _runStartedClients; private int _availableWorkloads = -1; - private ParallelRunDataAggregator _currentRunDataAggregator; + private ParallelRunDataAggregator? _currentRunDataAggregator; private readonly IRequestData _requestData; private bool _skipDefaultAdapters; @@ -140,15 +138,15 @@ public void Close() public bool HandlePartialRunComplete( IProxyExecutionManager proxyExecutionManager, TestRunCompleteEventArgs testRunCompleteArgs, - TestRunChangedEventArgs lastChunkArgs, - ICollection runContextAttachments, - ICollection executorUris) + TestRunChangedEventArgs? lastChunkArgs, + ICollection? runContextAttachments, + ICollection? executorUris) { var allRunsCompleted = false; // TODO: Interlocked.Increment _runCompletedClients, and the condition on the bottom probably does not need to be under lock?? lock (_executionStatusLockObject) { - // Each concurrent Executor calls this method + // Each concurrent Executor calls this method // So, we need to keep track of total run complete calls _runCompletedClients++; @@ -214,7 +212,7 @@ private List> SplitToWorkloads(TestRun // At that point we know that at least one testhost is not busy doing work anymore. It either // processed the workload and waits for another one, or it crashed and we should move to // another source. - // + // // In the "partial" step we check if we have more workloads, and if the currently running testhost // is shared we try to find a workload that is appropriate for it. If we don't find any work that the // running testhost can do. Or if the testhost already exited (possibly because of crash), we start another one @@ -303,7 +301,7 @@ private List> SplitToWorkloads(TestRun return workloads; - TestRunCriteria CreateTestRunCriteriaFromTestCasesAndSettings(IEnumerable testCases, TestRunCriteria criteria, string runsettingsXml) + TestRunCriteria CreateTestRunCriteriaFromTestCasesAndSettings(IEnumerable testCases, TestRunCriteria criteria, string? runsettingsXml) { return new TestRunCriteria( testCases, @@ -316,7 +314,7 @@ TestRunCriteria CreateTestRunCriteriaFromTestCasesAndSettings(IEnumerable sources, TestRunCriteria criteria, string runsettingsXml) + TestRunCriteria CreateTestRunCriteriaFromSourceAndSettings(IEnumerable sources, TestRunCriteria criteria, string? runsettingsXml) { return new TestRunCriteria( sources, @@ -334,9 +332,10 @@ TestRunCriteria CreateTestRunCriteriaFromSourceAndSettings(IEnumerable s private ParallelRunEventsHandler GetParallelEventHandler(IInternalTestRunEventsHandler eventHandler, IProxyExecutionManager concurrentManager) { - if (concurrentManager is ProxyExecutionManagerWithDataCollection) + TPDebug.Assert(_currentRunDataAggregator is not null, "_currentRunDataAggregator is null"); + + if (concurrentManager is ProxyExecutionManagerWithDataCollection concurrentManagerWithDataCollection) { - var concurrentManagerWithDataCollection = concurrentManager as ProxyExecutionManagerWithDataCollection; var attachmentsProcessingManager = new TestRunAttachmentsProcessingManager(TestPlatformEventSource.Instance, new DataCollectorAttachmentsProcessorsFactory()); return new ParallelDataCollectionEventsHandler( @@ -387,9 +386,10 @@ private void StartTestRunOnConcurrentManager(IProxyExecutionManager proxyExecuti EqtTrace.Error("ParallelProxyExecutionManager: Failed to trigger execution. Exception: " + t.Exception); var handler = eventHandler; - var testMessagePayload = new TestMessagePayload { MessageLevel = TestMessageLevel.Error, Message = t.Exception.ToString() }; + var exceptionToString = t.Exception?.ToString(); + var testMessagePayload = new TestMessagePayload { MessageLevel = TestMessageLevel.Error, Message = exceptionToString }; handler.HandleRawMessage(_dataSerializer.SerializePayload(MessageType.TestMessage, testMessagePayload)); - handler.HandleLogMessage(TestMessageLevel.Error, t.Exception.ToString()); + handler.HandleLogMessage(TestMessageLevel.Error, exceptionToString); // Send a run complete to caller. Similar logic is also used in ProxyExecutionManager.StartTestRun // Differences: diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelRunDataAggregator.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelRunDataAggregator.cs index c6968b56b6..22a0ff14b4 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelRunDataAggregator.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelRunDataAggregator.cs @@ -12,8 +12,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client.Parallel; /// @@ -125,9 +123,9 @@ public IDictionary GetAggregatedRunDataMetrics() return _metricsAggregator; } - public Exception GetAggregatedException() + public Exception? GetAggregatedException() { - return Exceptions == null || Exceptions.Count < 1 ? null : (Exception)new AggregateException(Exceptions); + return Exceptions == null || Exceptions.Count < 1 ? null : new AggregateException(Exceptions); } /// @@ -135,16 +133,16 @@ public Exception GetAggregatedException() /// Must be thread-safe as this is expected to be called by parallel managers /// public void Aggregate( - ITestRunStatistics testRunStats, - ICollection executorUris, - Exception exception, + ITestRunStatistics? testRunStats, + ICollection? executorUris, + Exception? exception, TimeSpan elapsedTime, bool isAborted, bool isCanceled, - ICollection runContextAttachments, - Collection runCompleteArgsAttachments, - Collection invokedDataCollectors, - Dictionary> discoveredExtensions) + ICollection? runContextAttachments, + Collection? runCompleteArgsAttachments, + Collection? invokedDataCollectors, + Dictionary>? discoveredExtensions) { lock (_dataUpdateSyncObject) { @@ -185,7 +183,7 @@ public void Aggregate( /// Aggregates Run Data Metrics from each Test Host Process /// /// - public void AggregateRunDataMetrics(IDictionary metrics) + public void AggregateRunDataMetrics(IDictionary? metrics) { if (metrics == null || metrics.Count == 0 || _metricsAggregator == null) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelRunEventsHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelRunEventsHandler.cs index 1e32f0cc65..19f5c540b3 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelRunEventsHandler.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelRunEventsHandler.cs @@ -14,8 +14,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client.Parallel; /// @@ -64,9 +62,9 @@ internal ParallelRunEventsHandler(IRequestData requestData, /// public virtual void HandleTestRunComplete( TestRunCompleteEventArgs testRunCompleteArgs, - TestRunChangedEventArgs lastChunkArgs, - ICollection runContextAttachments, - ICollection executorUris) + TestRunChangedEventArgs? lastChunkArgs, + ICollection? runContextAttachments, + ICollection? executorUris) { var parallelRunComplete = HandleSingleTestRunComplete(testRunCompleteArgs, lastChunkArgs, runContextAttachments, executorUris); @@ -101,9 +99,9 @@ public virtual void HandleTestRunComplete( } protected bool HandleSingleTestRunComplete(TestRunCompleteEventArgs testRunCompleteArgs, - TestRunChangedEventArgs lastChunkArgs, - ICollection runContextAttachments, - ICollection executorUris) + TestRunChangedEventArgs? lastChunkArgs, + ICollection? runContextAttachments, + ICollection? executorUris) { // we get run complete events from each executor process // so we cannot "complete" the actual executor operation until all sources/testcases are consumed diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs index bc412913b8..bdf8a5a727 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs @@ -19,8 +19,6 @@ using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// @@ -28,18 +26,18 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// public class ProxyDiscoveryManager : IProxyDiscoveryManager, IBaseProxy, ITestDiscoveryEventsHandler2 { - private readonly TestSessionInfo _testSessionInfo; - private readonly Func _proxyOperationManagerCreator; + private readonly TestSessionInfo? _testSessionInfo; + private readonly Func? _proxyOperationManagerCreator; private readonly DiscoveryDataAggregator _discoveryDataAggregator; private readonly IFileHelper _fileHelper; private readonly IDataSerializer _dataSerializer; - private ITestRuntimeProvider _testHostManager; + private ITestRuntimeProvider? _testHostManager; private bool _isCommunicationEstablished; - private ProxyOperationManager _proxyOperationManager; - private ITestDiscoveryEventsHandler2 _baseTestDiscoveryEventsHandler; + private ProxyOperationManager? _proxyOperationManager; + private ITestDiscoveryEventsHandler2? _baseTestDiscoveryEventsHandler; private bool _skipDefaultAdapters; - private string _previousSource; + private string? _previousSource; /// /// Initializes a new instance of the class. @@ -102,10 +100,10 @@ internal ProxyDiscoveryManager( IRequestData requestData, ITestRequestSender requestSender, ITestRuntimeProvider testHostManager, - Framework testhostManagerFramework, - DiscoveryDataAggregator discoveryDataAggregator = null, - IDataSerializer dataSerializer = null, - IFileHelper fileHelper = null) + Framework? testhostManagerFramework, + DiscoveryDataAggregator? discoveryDataAggregator = null, + IDataSerializer? dataSerializer = null, + IFileHelper? fileHelper = null) { _testHostManager = testHostManager; _discoveryDataAggregator = discoveryDataAggregator ?? new(); @@ -133,9 +131,9 @@ public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEve if (_proxyOperationManager == null) { + TPDebug.Assert(_proxyOperationManagerCreator is not null, "_proxyOperationManagerCreator is null"); // Passing only first because that is how the testhost pool is keyed. _proxyOperationManager = _proxyOperationManagerCreator(discoverySources[0], this); - _testHostManager = _proxyOperationManager.TestHostManager; } @@ -153,6 +151,7 @@ public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEve if (_isCommunicationEstablished) { InitializeExtensions(discoverySources); + TPDebug.Assert(_testHostManager is not null, "_testHostManager is null"); discoveryCriteria.UpdateDiscoveryCriteria(_testHostManager); // Consider the first source as the previous source so that if we are discovering a source @@ -257,7 +256,7 @@ public void Close() } /// - public void HandleDiscoveryComplete(DiscoveryCompleteEventArgs discoveryCompleteEventArgs, IEnumerable lastChunk) + public void HandleDiscoveryComplete(DiscoveryCompleteEventArgs discoveryCompleteEventArgs, IEnumerable? lastChunk) { // Currently, TestRequestSender always passes null for lastChunk in case of an aborted // discovery but we are not making this assumption here to ease potential future @@ -275,14 +274,14 @@ public void HandleDiscoveryComplete(DiscoveryCompleteEventArgs discoveryComplete _discoveryDataAggregator.MarkSourcesWithStatus(new[] { _previousSource }, DiscoveryStatus.FullyDiscovered); _previousSource = null; } - _baseTestDiscoveryEventsHandler.HandleDiscoveryComplete(discoveryCompleteEventArgs, lastChunk); + _baseTestDiscoveryEventsHandler?.HandleDiscoveryComplete(discoveryCompleteEventArgs, lastChunk); } /// public void HandleDiscoveredTests(IEnumerable discoveredTestCases) { _previousSource = _discoveryDataAggregator.MarkSourcesBasedOnDiscoveredTestCases(_previousSource, discoveredTestCases); - _baseTestDiscoveryEventsHandler.HandleDiscoveredTests(discoveredTestCases); + _baseTestDiscoveryEventsHandler?.HandleDiscoveredTests(discoveredTestCases); } /// @@ -294,13 +293,13 @@ public void HandleRawMessage(string rawMessage) Close(); } - _baseTestDiscoveryEventsHandler.HandleRawMessage(rawMessage); + _baseTestDiscoveryEventsHandler?.HandleRawMessage(rawMessage); } /// public void HandleLogMessage(TestMessageLevel level, string message) { - _baseTestDiscoveryEventsHandler.HandleLogMessage(level, message); + _baseTestDiscoveryEventsHandler?.HandleLogMessage(level, message); } #endregion @@ -310,8 +309,8 @@ public void HandleLogMessage(TestMessageLevel level, string message) public virtual TestProcessStartInfo UpdateTestProcessStartInfo(TestProcessStartInfo testProcessStartInfo) { // Update Telemetry Opt in status because by default in Test Host Telemetry is opted out - var telemetryOptedIn = _proxyOperationManager.RequestData.IsTelemetryOptedIn ? "true" : "false"; - testProcessStartInfo.Arguments += " --telemetryoptedin " + telemetryOptedIn; + var telemetryOptedIn = _proxyOperationManager?.RequestData?.IsTelemetryOptedIn == true ? "true" : "false"; + testProcessStartInfo.Arguments += $" --telemetryoptedin {telemetryOptedIn}"; return testProcessStartInfo; } #endregion @@ -328,12 +327,12 @@ private void InitializeExtensions(IEnumerable sources) } var sourceList = sources.ToList(); - var platformExtensions = _testHostManager.GetTestPlatformExtensions(sourceList, extensions.Except(nonExistingExtensions)); + var platformExtensions = _testHostManager?.GetTestPlatformExtensions(sourceList, extensions.Except(nonExistingExtensions)); // Only send this if needed. - if (platformExtensions.Any()) + if (platformExtensions is not null && platformExtensions.Any()) { - _proxyOperationManager.RequestSender.InitializeDiscovery(platformExtensions); + _proxyOperationManager?.RequestSender.InitializeDiscovery(platformExtensions); } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs index e55bb30182..10e84f0ce8 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs @@ -24,8 +24,6 @@ using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// @@ -33,20 +31,18 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// internal class ProxyExecutionManager : IProxyExecutionManager, IBaseProxy, IInternalTestRunEventsHandler { - private readonly TestSessionInfo _testSessionInfo; - private readonly Func _proxyOperationManagerCreator; - - private ITestRuntimeProvider _testHostManager; - + private readonly TestSessionInfo? _testSessionInfo; + private readonly Func? _proxyOperationManagerCreator; private readonly IFileHelper _fileHelper; private readonly IDataSerializer _dataSerializer; - private List _testSources; - private bool _isCommunicationEstablished; + private readonly bool _debugEnabledForTestSession; - private ProxyOperationManager _proxyOperationManager; - private IInternalTestRunEventsHandler _baseTestRunEventsHandler; + private List? _testSources; + private ITestRuntimeProvider? _testHostManager; + private bool _isCommunicationEstablished; + private ProxyOperationManager? _proxyOperationManager; + private IInternalTestRunEventsHandler? _baseTestRunEventsHandler; private bool _skipDefaultAdapters; - private readonly bool _debugEnabledForTestSession; /// public bool IsInitialized { get; private set; } @@ -56,8 +52,16 @@ internal class ProxyExecutionManager : IProxyExecutionManager, IBaseProxy, IInte /// public CancellationTokenSource CancellationTokenSource { - get { return _proxyOperationManager.CancellationTokenSource; } - set { _proxyOperationManager.CancellationTokenSource = value; } + get + { + TPDebug.Assert(_proxyOperationManager is not null, "_proxyOperationManager is null"); + return _proxyOperationManager.CancellationTokenSource; + } + set + { + TPDebug.Assert(_proxyOperationManager is not null, "_proxyOperationManager is null"); + _proxyOperationManager.CancellationTokenSource = value; + } } /// /// Initializes a new instance of the class. @@ -161,6 +165,8 @@ public virtual int StartTestRun(TestRunCriteria testRunCriteria, IInternalTestRu ? TestSourcesUtility.GetSources(testRunCriteria.Tests) : testRunCriteria.Sources; + TPDebug.Assert(_proxyOperationManagerCreator is not null, "_proxyOperationManagerCreator is null"); + TPDebug.Assert(sources is not null, "sources is null"); _proxyOperationManager = _proxyOperationManagerCreator( sources.First(), this); @@ -175,9 +181,9 @@ public virtual int StartTestRun(TestRunCriteria testRunCriteria, IInternalTestRu _testSources = new List( testRunCriteria.HasSpecificSources - ? testRunCriteria.Sources - // If the test execution is with a test filter, group them by sources. - : testRunCriteria.Tests.GroupBy(tc => tc.Source).Select(g => g.Key)); + ? testRunCriteria.Sources + // If the test execution is with a test filter, group them by sources. + : testRunCriteria.Tests.GroupBy(tc => tc.Source).Select(g => g.Key)); _isCommunicationEstablished = _proxyOperationManager.SetupChannel( _testSources, @@ -339,7 +345,7 @@ public void Close() /// public virtual int LaunchProcessWithDebuggerAttached(TestProcessStartInfo testProcessStartInfo) { - return _baseTestRunEventsHandler.LaunchProcessWithDebuggerAttached(testProcessStartInfo); + return _baseTestRunEventsHandler?.LaunchProcessWithDebuggerAttached(testProcessStartInfo) ?? -1; } /// @@ -350,7 +356,7 @@ public bool AttachDebuggerToProcess(AttachDebuggerInfo attachDebuggerInfo) // of this capability. if (attachDebuggerInfo.TargetFramework is null) { - attachDebuggerInfo.TargetFramework = _proxyOperationManager.TestHostManagerFramework.ToString(); + attachDebuggerInfo.TargetFramework = _proxyOperationManager?.TestHostManagerFramework?.ToString(); }; if (attachDebuggerInfo.Sources is null || !attachDebuggerInfo.Sources.Any()) @@ -358,19 +364,19 @@ public bool AttachDebuggerToProcess(AttachDebuggerInfo attachDebuggerInfo) attachDebuggerInfo.Sources = _testSources; } - return _baseTestRunEventsHandler.AttachDebuggerToProcess(attachDebuggerInfo); + return _baseTestRunEventsHandler?.AttachDebuggerToProcess(attachDebuggerInfo) ?? false; } /// - public void HandleTestRunComplete(TestRunCompleteEventArgs testRunCompleteArgs, TestRunChangedEventArgs lastChunkArgs, ICollection runContextAttachments, ICollection executorUris) + public void HandleTestRunComplete(TestRunCompleteEventArgs testRunCompleteArgs, TestRunChangedEventArgs? lastChunkArgs, ICollection? runContextAttachments, ICollection? executorUris) { - _baseTestRunEventsHandler.HandleTestRunComplete(testRunCompleteArgs, lastChunkArgs, runContextAttachments, executorUris); + _baseTestRunEventsHandler?.HandleTestRunComplete(testRunCompleteArgs, lastChunkArgs, runContextAttachments, executorUris); } /// public void HandleTestRunStatsChange(TestRunChangedEventArgs testRunChangedArgs) { - _baseTestRunEventsHandler.HandleTestRunStatsChange(testRunChangedArgs); + _baseTestRunEventsHandler?.HandleTestRunStatsChange(testRunChangedArgs); } /// @@ -386,13 +392,13 @@ public void HandleRawMessage(string rawMessage) Close(); } - _baseTestRunEventsHandler.HandleRawMessage(rawMessage); + _baseTestRunEventsHandler?.HandleRawMessage(rawMessage); } /// public void HandleLogMessage(TestMessageLevel level, string message) { - _baseTestRunEventsHandler.HandleLogMessage(level, message); + _baseTestRunEventsHandler?.HandleLogMessage(level, message); } #endregion @@ -402,7 +408,7 @@ public void HandleLogMessage(TestMessageLevel level, string message) public virtual TestProcessStartInfo UpdateTestProcessStartInfo(TestProcessStartInfo testProcessStartInfo) { // Update Telemetry Opt in status because by default in Test Host Telemetry is opted out - var telemetryOptedIn = _proxyOperationManager.RequestData.IsTelemetryOptedIn ? "true" : "false"; + var telemetryOptedIn = _proxyOperationManager?.RequestData?.IsTelemetryOptedIn == true ? "true" : "false"; testProcessStartInfo.Arguments += " --telemetryoptedin " + telemetryOptedIn; return testProcessStartInfo; } @@ -421,7 +427,7 @@ public virtual TestProcessStartInfo UpdateTestProcessStartInfo(TestProcessStartI /// public virtual bool SetupChannel(IEnumerable sources, string runSettings) { - return _proxyOperationManager.SetupChannel(sources, runSettings); + return _proxyOperationManager?.SetupChannel(sources, runSettings) ?? false; } private void LogMessage(TestMessageLevel testMessageLevel, string message) @@ -447,12 +453,12 @@ private void InitializeExtensions(IEnumerable sources) } var sourceList = sources.ToList(); - var platformExtensions = _testHostManager.GetTestPlatformExtensions(sourceList, extensions.Except(nonExistingExtensions)); + var platformExtensions = _testHostManager?.GetTestPlatformExtensions(sourceList, extensions.Except(nonExistingExtensions)); // Only send this if needed. - if (platformExtensions.Any()) + if (platformExtensions is not null && platformExtensions.Any()) { - _proxyOperationManager.RequestSender.InitializeExecution(platformExtensions); + _proxyOperationManager?.RequestSender.InitializeExecution(platformExtensions); } } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManagerWithDataCollection.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManagerWithDataCollection.cs index da4d95bae0..1d0ff0a114 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManagerWithDataCollection.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManagerWithDataCollection.cs @@ -13,8 +13,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// @@ -22,7 +20,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// internal class ProxyExecutionManagerWithDataCollection : ProxyExecutionManager { - private IDictionary _dataCollectionEnvironmentVariables; + private IDictionary? _dataCollectionEnvironmentVariables; private int _dataCollectionPort; private readonly IRequestData _requestData; @@ -61,7 +59,7 @@ public ProxyExecutionManagerWithDataCollection( testHostManager.HostLaunched += TestHostLaunchedHandler; } - private void TestHostLaunchedHandler(object sender, HostProviderEventArgs e) + private void TestHostLaunchedHandler(object? sender, HostProviderEventArgs e) { ProxyDataCollectionManager.TestHostLaunched(e.ProcessId); } @@ -178,7 +176,7 @@ public override TestProcessStartInfo UpdateTestProcessStartInfo(TestProcessStart { testProcessStartInfo.EnvironmentVariables = _dataCollectionEnvironmentVariables; } - else + else if (_dataCollectionEnvironmentVariables is not null) { foreach (var kvp in _dataCollectionEnvironmentVariables) { @@ -188,8 +186,7 @@ public override TestProcessStartInfo UpdateTestProcessStartInfo(TestProcessStart // Update Telemetry Opt in status because by default in Test Host Telemetry is opted out var telemetryOptedIn = _requestData.IsTelemetryOptedIn ? "true" : "false"; - testProcessStartInfo.Arguments += " --datacollectionport " + _dataCollectionPort - + " --telemetryoptedin " + telemetryOptedIn; + testProcessStartInfo.Arguments += $" --datacollectionport {_dataCollectionPort} --telemetryoptedin {telemetryOptedIn}"; return testProcessStartInfo; } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs index 6d80225e45..dc2f02b9bf 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs @@ -25,8 +25,6 @@ using CoreUtilitiesConstants = Microsoft.VisualStudio.TestPlatform.CoreUtilities.Constants; using CrossPlatEngineResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// @@ -38,15 +36,15 @@ public class ProxyOperationManager private readonly string _makeRunsettingsCompatiblePropertyName = "MakeRunsettingsCompatible"; private readonly ManualResetEventSlim _testHostExited = new(false); private readonly IProcessHelper _processHelper; + private readonly IBaseProxy? _baseProxy; - private readonly IBaseProxy _baseProxy; private bool _versionCheckRequired = true; private bool _makeRunsettingsCompatible; private bool _makeRunsettingsCompatibleSet; private bool _initialized; private bool _testHostLaunched; private int _testHostProcessId; - private string _testHostProcessStdError; + private string? _testHostProcessStdError; /// /// Initializes a new instance of the class. @@ -56,7 +54,7 @@ public class ProxyOperationManager /// Request sender instance. /// Test host manager instance. public ProxyOperationManager( - IRequestData requestData, + IRequestData? requestData, ITestRequestSender requestSender, ITestRuntimeProvider testHostManager, Framework testhostManagerFramework) @@ -77,11 +75,11 @@ public ProxyOperationManager( /// Test host manager instance. /// The base proxy. public ProxyOperationManager( - IRequestData requestData, + IRequestData? requestData, ITestRequestSender requestSender, ITestRuntimeProvider testHostManager, - Framework testhostManagerFramework, - IBaseProxy baseProxy) + Framework? testhostManagerFramework, + IBaseProxy? baseProxy) { RequestData = requestData; RequestSender = requestSender; @@ -99,7 +97,7 @@ public ProxyOperationManager( /// /// Gets or sets the request data. /// - public IRequestData RequestData { get; set; } + public IRequestData? RequestData { get; set; } /// /// Gets or sets the server for communication. @@ -121,7 +119,7 @@ public ProxyOperationManager( /// public CancellationTokenSource CancellationTokenSource { get; set; } - public Framework TestHostManagerFramework { get; } + public Framework? TestHostManagerFramework { get; } #region IProxyOperationManager implementation. /// @@ -168,7 +166,7 @@ public virtual bool SetupChannel( /// /// Returns true if the communication is established b/w runner and host, false otherwise. /// - public virtual bool SetupChannel(IEnumerable sources, string runSettings) + public virtual bool SetupChannel(IEnumerable sources, string? runSettings) { CancellationTokenSource.Token.ThrowTestPlatformExceptionIfCancellationRequested(); @@ -240,10 +238,10 @@ public virtual bool SetupChannel(IEnumerable sources, string runSettings var hostDebugEnabled = Environment.GetEnvironmentVariable("VSTEST_HOST_DEBUG"); var nativeHostDebugEnabled = Environment.GetEnvironmentVariable("VSTEST_HOST_NATIVE_DEBUG"); - if ((!string.IsNullOrEmpty(hostDebugEnabled) + if ((!StringUtils.IsNullOrEmpty(hostDebugEnabled) && hostDebugEnabled.Equals("1", StringComparison.Ordinal)) || (new PlatformEnvironment().OperatingSystem.Equals(PlatformOperatingSystem.Windows) - && !string.IsNullOrEmpty(nativeHostDebugEnabled) + && !StringUtils.IsNullOrEmpty(nativeHostDebugEnabled) && nativeHostDebugEnabled.Equals("1", StringComparison.Ordinal))) { ConsoleOutput.Instance.WriteLine( @@ -366,7 +364,7 @@ public virtual TestProcessStartInfo UpdateTestProcessStartInfo(TestProcessStartI if (_baseProxy == null) { // Update Telemetry Opt in status because by default in Test Host Telemetry is opted out - var telemetryOptedIn = RequestData.IsTelemetryOptedIn ? "true" : "false"; + var telemetryOptedIn = RequestData?.IsTelemetryOptedIn == true ? "true" : "false"; testProcessStartInfo.Arguments += " --telemetryoptedin " + telemetryOptedIn; return testProcessStartInfo; } @@ -383,7 +381,7 @@ public virtual TestProcessStartInfo UpdateTestProcessStartInfo(TestProcessStartI /// Run settings string. /// /// The run settings after removing non-required nodes. - public string RemoveNodesFromRunsettingsIfRequired(string runsettingsXml, Action logMessage) + public string? RemoveNodesFromRunsettingsIfRequired(string runsettingsXml, Action logMessage) { var updatedRunSettingsXml = runsettingsXml; if (!_makeRunsettingsCompatibleSet) @@ -405,9 +403,9 @@ public string RemoveNodesFromRunsettingsIfRequired(string runsettingsXml, Action return updatedRunSettingsXml; } - private string GetTimestampedLogFile(string logFile) + private static string? GetTimestampedLogFile(string? logFile) { - return string.IsNullOrWhiteSpace(logFile) + return logFile.IsNullOrWhiteSpace() ? null : Path.ChangeExtension( logFile, @@ -428,24 +426,24 @@ private void CompatIssueWithVersionCheckAndRunsettings() var versionCheckProperty = properties.FirstOrDefault(p => string.Equals(p.Name, _versionCheckPropertyName, StringComparison.OrdinalIgnoreCase)); if (versionCheckProperty != null) { - _versionCheckRequired = (bool)versionCheckProperty.GetValue(TestHostManager); + _versionCheckRequired = (bool)versionCheckProperty.GetValue(TestHostManager)!; } var makeRunsettingsCompatibleProperty = properties.FirstOrDefault(p => string.Equals(p.Name, _makeRunsettingsCompatiblePropertyName, StringComparison.OrdinalIgnoreCase)); if (makeRunsettingsCompatibleProperty != null) { - _makeRunsettingsCompatible = (bool)makeRunsettingsCompatibleProperty.GetValue(TestHostManager); + _makeRunsettingsCompatible = (bool)makeRunsettingsCompatibleProperty.GetValue(TestHostManager)!; _makeRunsettingsCompatibleSet = true; } } - private void TestHostManagerHostLaunched(object sender, HostProviderEventArgs e) + private void TestHostManagerHostLaunched(object? sender, HostProviderEventArgs e) { EqtTrace.Verbose(e.Data); _testHostProcessId = e.ProcessId; } - private void TestHostManagerHostExited(object sender, HostProviderEventArgs e) + private void TestHostManagerHostExited(object? sender, HostProviderEventArgs e) { EqtTrace.Verbose("CrossPlatEngine.TestHostManagerHostExited: calling on client process exit callback."); _testHostProcessStdError = e.Data; @@ -486,7 +484,7 @@ private void ThrowExceptionOnConnectionFailure(int connTimeout) } // After testhost process launched failed with error. - if (!string.IsNullOrWhiteSpace(_testHostProcessStdError)) + if (!StringUtils.IsNullOrWhiteSpace(_testHostProcessStdError)) { // Testhost failed with error. errorMsg = string.Format(CrossPlatEngineResources.TestHostExitedWithError, _testHostProcessStdError); diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManagerWithDataCollection.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManagerWithDataCollection.cs index 0622bb737c..a83c6bed74 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManagerWithDataCollection.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManagerWithDataCollection.cs @@ -10,8 +10,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// @@ -19,7 +17,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// public class ProxyOperationManagerWithDataCollection : ProxyOperationManager { - private IDictionary _dataCollectionEnvironmentVariables; + private IDictionary? _dataCollectionEnvironmentVariables; private readonly IRequestData _requestData; private int _dataCollectionPort; @@ -27,7 +25,7 @@ public class ProxyOperationManagerWithDataCollection : ProxyOperationManager /// Initializes a new instance of the /// class. /// - /// + /// /// The request data. /// The request sender. /// The test host manager. @@ -90,7 +88,7 @@ public override TestProcessStartInfo UpdateTestProcessStartInfo(TestProcessStart { testProcessStartInfo.EnvironmentVariables = _dataCollectionEnvironmentVariables; } - else + else if (_dataCollectionEnvironmentVariables is not null) { foreach (var kvp in _dataCollectionEnvironmentVariables) { @@ -100,8 +98,7 @@ public override TestProcessStartInfo UpdateTestProcessStartInfo(TestProcessStart // Update telemetry opt in status because by default test host telemetry is opted out. var telemetryOptedIn = _requestData.IsTelemetryOptedIn ? "true" : "false"; - testProcessStartInfo.Arguments += " --datacollectionport " + _dataCollectionPort - + " --telemetryoptedin " + telemetryOptedIn; + testProcessStartInfo.Arguments += $" --datacollectionport {_dataCollectionPort} --telemetryoptedin {telemetryOptedIn}"; return testProcessStartInfo; } @@ -142,7 +139,7 @@ internal IProxyDataCollectionManager ProxyDataCollectionManager get; private set; } - private void TestHostLaunchedHandler(object sender, HostProviderEventArgs e) + private void TestHostLaunchedHandler(object? sender, HostProviderEventArgs e) { ProxyDataCollectionManager.TestHostLaunched(e.ProcessId); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestLoggerManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestLoggerManager.cs index 5d54976576..0d6907e68d 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestLoggerManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestLoggerManager.cs @@ -23,8 +23,6 @@ using CommonResources = Microsoft.VisualStudio.TestPlatform.Common.Resources.Resources; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; /// @@ -46,12 +44,12 @@ internal class TestLoggerManager : ITestLoggerManager /// /// Test run directory. /// - private string _testRunDirectory; + private string? _testRunDirectory; /// /// Target framework. /// - private string _targetFramework; + private string? _targetFramework; /// /// TreatNoTestsAsError value; @@ -76,7 +74,7 @@ internal class TestLoggerManager : ITestLoggerManager /// /// Logger extension manager. /// - private TestLoggerExtensionManager _testLoggerExtensionManager; + private TestLoggerExtensionManager? _testLoggerExtensionManager; /// /// AssemblyLoadContext for current platform @@ -131,7 +129,7 @@ private TestLoggerExtensionManager TestLoggerExtensionManager /// /// Initializes all the loggers passed by user /// - public void Initialize(string runSettings) + public void Initialize(string? runSettings) { // Enable logger events EnableLogging(); @@ -155,14 +153,14 @@ public void Initialize(string runSettings) var loggerInitialized = false; // Try initializing logger by type. - if (!string.IsNullOrWhiteSpace(logger.AssemblyQualifiedName)) + if (!StringUtils.IsNullOrWhiteSpace(logger.AssemblyQualifiedName)) { loggerInitialized = InitializeLoggerByType(logger.AssemblyQualifiedName, logger.CodeBase, parameters); } // Try initializing logger by uri. if (!loggerInitialized && - !string.IsNullOrWhiteSpace(logger.Uri?.ToString())) + !StringUtils.IsNullOrWhiteSpace(logger.Uri?.ToString())) { loggerInitialized = InitializeLoggerByUri(logger.Uri, parameters); } @@ -178,9 +176,9 @@ public void Initialize(string runSettings) // Output error if logger is not initialized. if (!loggerInitialized) { - var value = !string.IsNullOrWhiteSpace(logger.AssemblyQualifiedName) + var value = !StringUtils.IsNullOrWhiteSpace(logger.AssemblyQualifiedName) ? logger.AssemblyQualifiedName - : !string.IsNullOrWhiteSpace(logger.Uri?.ToString()) + : !StringUtils.IsNullOrWhiteSpace(logger.Uri?.ToString()) ? logger.Uri.ToString() : logger.FriendlyName; @@ -356,7 +354,7 @@ public void Dispose() /// URI of the logger to add. /// Logger parameters. /// Logger Initialized flag. - internal bool InitializeLoggerByUri(Uri uri, Dictionary parameters) + internal bool InitializeLoggerByUri(Uri uri, Dictionary? parameters) { ValidateArg.NotNull(uri, nameof(uri)); CheckDisposed(); @@ -395,7 +393,7 @@ internal bool InitializeLoggerByUri(Uri uri, Dictionary paramete /// The friendly Name. /// The logger Uri. /// - internal bool TryGetUriFromFriendlyName(string friendlyName, out Uri loggerUri) + internal bool TryGetUriFromFriendlyName(string friendlyName, out Uri? loggerUri) { var extensionManager = TestLoggerExtensionManager; foreach (var extension in extensionManager.TestExtensions) @@ -430,9 +428,9 @@ internal bool TryGetUriFromFriendlyName(string friendlyName, out Uri loggerUri) /// /// Test run settings. /// Test results directory - internal string GetResultsDirectory(string runSettings) + internal string? GetResultsDirectory(string? runSettings) { - string resultsDirectory = null; + string? resultsDirectory = null; if (runSettings != null) { try @@ -454,9 +452,9 @@ internal string GetResultsDirectory(string runSettings) /// /// Test run settings. /// Target framework - internal Framework GetTargetFramework(string runSettings) + internal Framework? GetTargetFramework(string? runSettings) { - Framework targetFramework = null; + Framework? targetFramework = null; if (runSettings != null) { try @@ -478,7 +476,7 @@ internal Framework GetTargetFramework(string runSettings) /// /// /// - internal bool GetTreatNoTestsAsError(string runSettings) + internal bool GetTreatNoTestsAsError(string? runSettings) { return RunSettingsUtilities.GetTreatNoTestsAsError(runSettings); } @@ -522,7 +520,7 @@ internal virtual void Dispose(bool disposing) /// /// /// - private Dictionary GetParametersFromConfigurationElement(XmlElement configuration) + private static Dictionary GetParametersFromConfigurationElement(XmlElement configuration) { var configurationManager = new LoggerNameValueConfigurationManager(configuration); return configurationManager.NameValuePairs; @@ -535,7 +533,7 @@ private Dictionary GetParametersFromConfigurationElement(XmlElem /// Code base. /// Logger parameters. /// Logger Initialized flag. - private bool InitializeLoggerByType(string assemblyQualifiedName, string codeBase, Dictionary parameters) + private bool InitializeLoggerByType(string assemblyQualifiedName, string codeBase, Dictionary parameters) { CheckDisposed(); try @@ -544,7 +542,7 @@ private bool InitializeLoggerByType(string assemblyQualifiedName, string codeBas Assembly assembly = _assemblyLoadContext.LoadAssemblyFromPath(codeBase); var loggerType = assembly?.GetTypes() - .FirstOrDefault(x => x.AssemblyQualifiedName.Equals(assemblyQualifiedName)); + .FirstOrDefault(x => string.Equals(x.AssemblyQualifiedName, assemblyQualifiedName)); // Create logger instance var constructorInfo = loggerType?.GetConstructor(Type.EmptyTypes); @@ -582,7 +580,7 @@ private bool InitializeLoggerByType(string assemblyQualifiedName, string codeBas } } - private bool InitializeLogger(object logger, string extensionUri, Dictionary parameters) + private bool InitializeLogger(object? logger, string? extensionUri, Dictionary? parameters) { if (logger == null) { @@ -594,8 +592,7 @@ private bool InitializeLogger(object logger, string extensionUri, Dictionary /// Populates user supplied and default logger parameters. /// - private Dictionary UpdateLoggerParameters(Dictionary parameters) + private Dictionary UpdateLoggerParameters(Dictionary? parameters) { - var loggerParams = new Dictionary(StringComparer.OrdinalIgnoreCase); - if (parameters != null) - { - loggerParams = new Dictionary(parameters, StringComparer.OrdinalIgnoreCase); - } + var loggerParams = parameters is not null + ? new Dictionary(parameters, StringComparer.OrdinalIgnoreCase) + : new Dictionary(StringComparer.OrdinalIgnoreCase); // Add default logger parameters... loggerParams[DefaultLoggerParameterNames.TestRunDirectory] = _testRunDirectory; diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestRunCriteriaExtensions.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestRunCriteriaExtensions.cs index b0df14e444..16501c5acf 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestRunCriteriaExtensions.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestRunCriteriaExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.ObjectModel; @@ -9,16 +10,13 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; internal static class TestRunCriteriaExtensions { - public static TestRunCriteriaWithSources CreateTestRunCriteriaForSources(this TestRunCriteria testRunCriteria, ITestRuntimeProvider testRuntimeProvider, - string runSettings, TestExecutionContext executionContext, IEnumerable inputPackages) + public static TestRunCriteriaWithSources CreateTestRunCriteriaForSources(this TestRunCriteria testRunCriteria, ITestRuntimeProvider? testRuntimeProvider, string? runSettings, TestExecutionContext executionContext, IEnumerable? inputPackages) { - if (TryCheckTestSourceDifferFromPackage(testRuntimeProvider, inputPackages, out IEnumerable actualTestSources)) + if (TryCheckTestSourceDifferFromPackage(testRuntimeProvider, inputPackages, out IEnumerable? actualTestSources)) { UpdateTestSources(actualTestSources, testRunCriteria.AdapterSourceMap); } @@ -30,10 +28,10 @@ public static TestRunCriteriaWithSources CreateTestRunCriteriaForSources(this Te return new TestRunCriteriaWithSources(testRunCriteria.AdapterSourceMap, inputPackages?.FirstOrDefault(), runSettings, executionContext); } - public static TestRunCriteriaWithTests CreateTestRunCriteriaForTests(this TestRunCriteria testRunCriteria, ITestRuntimeProvider testRuntimeProvider, - string runSettings, TestExecutionContext executionContext, IEnumerable inputPackages) + public static TestRunCriteriaWithTests CreateTestRunCriteriaForTests(this TestRunCriteria testRunCriteria, ITestRuntimeProvider? testRuntimeProvider, + string? runSettings, TestExecutionContext executionContext, IEnumerable? inputPackages) { - if (TryCheckTestSourceDifferFromPackage(testRuntimeProvider, inputPackages, out IEnumerable actualTestSources)) + if (TryCheckTestSourceDifferFromPackage(testRuntimeProvider, inputPackages, out IEnumerable? actualTestSources)) { // In UWP scenario TestCase object contains the package as source, which is not actual test source for adapters, // so update test case before sending them. @@ -51,10 +49,15 @@ public static TestRunCriteriaWithTests CreateTestRunCriteriaForTests(this TestRu return new TestRunCriteriaWithTests(testRunCriteria.Tests, inputPackages?.FirstOrDefault(), runSettings, executionContext); } - private static bool TryCheckTestSourceDifferFromPackage(ITestRuntimeProvider testRuntimeProvider, - IEnumerable inputPackages, out IEnumerable actualTestSources) + private static bool TryCheckTestSourceDifferFromPackage(ITestRuntimeProvider? testRuntimeProvider, + IEnumerable? inputPackages, [NotNullWhen(true)] out IEnumerable? actualTestSources) { - actualTestSources = testRuntimeProvider.GetTestSources(inputPackages); + actualTestSources = testRuntimeProvider?.GetTestSources(inputPackages); + + if (inputPackages is null || actualTestSources is null) + { + return false; + } // For netcore/fullclr both packages and sources are same thing, // For UWP the actual source(exe) differs from input source(.appxrecipe) which we call package. diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestRuntimeProviderInfo.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestRuntimeProviderInfo.cs index 38374fdcfe..695c6eea03 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestRuntimeProviderInfo.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/TestRuntimeProviderInfo.cs @@ -12,10 +12,10 @@ public class TestRuntimeProviderInfo { public Type? Type { get; } public bool Shared { get; } - public string RunSettings { get; } + public string? RunSettings { get; } public List SourceDetails { get; } - public TestRuntimeProviderInfo(Type? type, bool shared, string runSettings, List sourceDetails) + public TestRuntimeProviderInfo(Type? type, bool shared, string? runSettings, List sourceDetails) { Type = type; Shared = shared; diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Constants.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Constants.cs index b22fa22632..59a12603f2 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Constants.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Constants.cs @@ -7,8 +7,6 @@ using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; /// diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionLauncher.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionLauncher.cs index e064fa0dfe..b99a5fa35f 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionLauncher.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionLauncher.cs @@ -11,8 +11,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -48,7 +46,7 @@ public DataCollectionLauncher(IProcessHelper processHelper, IMessageLogger messa /// /// Gets callback on process exit /// - protected Action ExitCallBack => (process) => + protected Action ExitCallBack => process => { var processStdErrorStr = _processStdError.ToString(); @@ -58,7 +56,7 @@ public DataCollectionLauncher(IProcessHelper processHelper, IMessageLogger messa { EqtTrace.Error("DataCollectionLauncher.ExitCallBack: Data collector exited with exitcode:{0} error: '{1}'", exitCode, processStdErrorStr); - if (!string.IsNullOrWhiteSpace(processStdErrorStr)) + if (!StringUtils.IsNullOrWhiteSpace(processStdErrorStr)) { _messageLogger.SendMessage(TestMessageLevel.Error, processStdErrorStr); } @@ -72,7 +70,7 @@ public DataCollectionLauncher(IProcessHelper processHelper, IMessageLogger messa /// /// Gets callback to read from process error stream /// - protected Action ErrorReceivedCallback => (process, data) => + protected Action ErrorReceivedCallback => (process, data) => { // Log all standard error message because on too much data we ignore starting part. // This is helpful in abnormal failure of datacollector. @@ -94,6 +92,6 @@ public DataCollectionLauncher(IProcessHelper processHelper, IMessageLogger messa /// The . /// public abstract int LaunchDataCollector( - IDictionary environmentVariables, + IDictionary? environmentVariables, IList commandLineArguments); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionLauncherFactory.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionLauncherFactory.cs index d1bde30045..d8157276fc 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionLauncherFactory.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionLauncherFactory.cs @@ -4,12 +4,9 @@ using System; using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -23,15 +20,16 @@ internal static class DataCollectionLauncherFactory /// /// The . /// - internal static IDataCollectionLauncher GetDataCollectorLauncher(IProcessHelper processHelper, string settingsXml) + internal static IDataCollectionLauncher GetDataCollectorLauncher(IProcessHelper processHelper, string? settingsXml) { // Event log datacollector is built for .NET Framework and we need to load inside .NET Framework process. - if (!string.IsNullOrWhiteSpace(settingsXml)) + if (!settingsXml.IsNullOrWhiteSpace()) { var dataCollectionRunSettings = XmlRunSettingsUtilities.GetDataCollectionRunSettings(settingsXml); foreach (var dataCollectorSettings in dataCollectionRunSettings.DataCollectorSettingsList) { - if (string.Equals(dataCollectorSettings.FriendlyName, "event Log", StringComparison.OrdinalIgnoreCase) || string.Equals(dataCollectorSettings.Uri?.ToString(), @"datacollector://Microsoft/EventLog/2.0", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(dataCollectorSettings.FriendlyName, "event Log", StringComparison.OrdinalIgnoreCase) + || string.Equals(dataCollectorSettings.Uri?.ToString(), @"datacollector://Microsoft/EventLog/2.0", StringComparison.OrdinalIgnoreCase)) { return new DefaultDataCollectionLauncher(); } @@ -40,6 +38,7 @@ internal static IDataCollectionLauncher GetDataCollectorLauncher(IProcessHelper // Target Framework of DataCollection process and Runner should be same. var currentProcessPath = processHelper.GetCurrentProcessFileName(); + TPDebug.Assert(currentProcessPath is not null, "currentProcessPath is null"); return currentProcessPath.EndsWith("dotnet", StringComparison.OrdinalIgnoreCase) || currentProcessPath.EndsWith("dotnet.exe", StringComparison.OrdinalIgnoreCase) diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionParameters.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionParameters.cs index 0717fc498a..923d9e5f78 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionParameters.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionParameters.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -26,7 +24,7 @@ public class DataCollectionParameters /// public DataCollectionParameters( bool areTestCaseLevelEventsRequired, - IDictionary environmentVariables, + IDictionary? environmentVariables, int dataCollectionEventsPort) { AreTestCaseLevelEventsRequired = areTestCaseLevelEventsRequired; @@ -43,7 +41,7 @@ public DataCollectionParameters( /// /// Gets BeforeTestRunStart Call on the DataCollectors can yield/return a set of environment variables /// - public IDictionary EnvironmentVariables { get; private set; } + public IDictionary? EnvironmentVariables { get; private set; } /// /// Gets the data collection events port. diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionResult.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionResult.cs index c6a1867e8a..01257d67ff 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionResult.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionResult.cs @@ -5,8 +5,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -14,7 +12,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// public class DataCollectionResult { - public DataCollectionResult(Collection attachments, Collection invokedDataCollectors) + public DataCollectionResult(Collection? attachments, Collection? invokedDataCollectors) { Attachments = attachments; InvokedDataCollectors = invokedDataCollectors; @@ -23,10 +21,10 @@ public DataCollectionResult(Collection attachments, Collection /// Get list of attachments /// - public Collection Attachments { get; } + public Collection? Attachments { get; } /// /// Get the list of the invoked data collectors. /// - public Collection InvokedDataCollectors { get; } + public Collection? InvokedDataCollectors { get; } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionTestRunEventsHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionTestRunEventsHandler.cs index 18883a30ab..dc4f1d62d2 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionTestRunEventsHandler.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionTestRunEventsHandler.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; @@ -15,8 +16,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -27,10 +26,11 @@ internal class DataCollectionTestRunEventsHandler : IInternalTestRunEventsHandle { private readonly IProxyDataCollectionManager _proxyDataCollectionManager; private readonly IInternalTestRunEventsHandler _testRunEventsHandler; - private CancellationToken _cancellationToken; + private readonly CancellationToken _cancellationToken; private readonly IDataSerializer _dataSerializer; - private Collection _dataCollectionAttachmentSets; - private Collection _invokedDataCollectors; + + private Collection? _dataCollectionAttachmentSets; + private Collection? _invokedDataCollectors; /// /// Initializes a new instance of the class. @@ -75,7 +75,7 @@ public DataCollectionTestRunEventsHandler(IInternalTestRunEventsHandler baseTest /// /// The message. /// - public void HandleLogMessage(TestMessageLevel level, string message) + public void HandleLogMessage(TestMessageLevel level, string? message) { _testRunEventsHandler.HandleLogMessage(level, message); } @@ -102,7 +102,7 @@ public void HandleRawMessage(string rawMessage) if (_dataCollectionAttachmentSets != null && _dataCollectionAttachmentSets.Any()) { GetCombinedAttachmentSets( - testRunCompletePayload.TestRunCompleteArgs.AttachmentSets, + testRunCompletePayload?.TestRunCompleteArgs?.AttachmentSets, _dataCollectionAttachmentSets); } @@ -111,7 +111,7 @@ public void HandleRawMessage(string rawMessage) { foreach (var dataCollector in _invokedDataCollectors) { - testRunCompletePayload.TestRunCompleteArgs.InvokedDataCollectors.Add(dataCollector); + testRunCompletePayload?.TestRunCompleteArgs?.InvokedDataCollectors.Add(dataCollector); } } @@ -138,7 +138,7 @@ public void HandleRawMessage(string rawMessage) /// /// The executor uris. /// - public void HandleTestRunComplete(TestRunCompleteEventArgs testRunCompleteArgs, TestRunChangedEventArgs lastChunkArgs, ICollection runContextAttachments, ICollection executorUris) + public void HandleTestRunComplete(TestRunCompleteEventArgs testRunCompleteArgs, TestRunChangedEventArgs? lastChunkArgs, ICollection? runContextAttachments, ICollection? executorUris) { if (_dataCollectionAttachmentSets != null && _dataCollectionAttachmentSets.Any()) { @@ -198,7 +198,9 @@ public bool AttachDebuggerToProcess(AttachDebuggerInfo attachDebuggerInfo) /// /// The . /// - internal static ICollection GetCombinedAttachmentSets(Collection originalAttachmentSets, ICollection newAttachments) + [return: NotNullIfNotNull("originalAttachmentSets")] + [return: NotNullIfNotNull("newAttachments")] + internal static ICollection? GetCombinedAttachmentSets(Collection? originalAttachmentSets, ICollection? newAttachments) { if (newAttachments == null || newAttachments.Count == 0) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DefaultDataCollectionLauncher.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DefaultDataCollectionLauncher.cs index 2729a0a83f..97ce9bc9b9 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DefaultDataCollectionLauncher.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DefaultDataCollectionLauncher.cs @@ -11,8 +11,6 @@ using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -53,11 +51,13 @@ internal DefaultDataCollectionLauncher(IProcessHelper processHelper, IMessageLog /// Environment variables for the process. /// The command line arguments to pass to the process. /// ProcessId of launched Process. 0 means not launched. - public override int LaunchDataCollector(IDictionary environmentVariables, IList commandLineArguments) + public override int LaunchDataCollector(IDictionary? environmentVariables, IList commandLineArguments) { var dataCollectorDirectory = Path.GetDirectoryName(typeof(DefaultDataCollectionLauncher).GetTypeInfo().Assembly.GetAssemblyLocation()); + TPDebug.Assert(dataCollectorDirectory is not null, "dataCollectorDirectory is not null"); var currentProcessPath = _processHelper.GetCurrentProcessFileName(); + TPDebug.Assert(currentProcessPath is not null, "currentProcessPath is not null"); // If current process is dotnet/dotnet.exe and you are here, datacollector.exe/datacollector.arm64.exe is present in TestHost folder. string dataCollectorProcessName = _processHelper.GetCurrentProcessArchitecture() == PlatformArchitecture.ARM64 ? DataCollectorProcessNameArm64 : DataCollectorProcessName; diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DotnetDataCollectionLauncher.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DotnetDataCollectionLauncher.cs index 67387916b0..a6e40a9e4e 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DotnetDataCollectionLauncher.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DotnetDataCollectionLauncher.cs @@ -14,8 +14,6 @@ using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -61,15 +59,12 @@ internal DotnetDataCollectionLauncher(IProcessHelper processHelper, IFileHelper /// Environment variables for the process. /// The command line arguments to pass to the process. /// ProcessId of launched Process. 0 means not launched. - public override int LaunchDataCollector(IDictionary environmentVariables, IList commandLineArguments) + public override int LaunchDataCollector(IDictionary? environmentVariables, IList commandLineArguments) { var dataCollectorDirectory = Path.GetDirectoryName(typeof(DefaultDataCollectionLauncher).GetTypeInfo().Assembly.GetAssemblyLocation()); - var currentProcessFileName = _processHelper.GetCurrentProcessFileName(); - - EqtTrace.Verbose("DotnetDataCollectionLauncher: Full path of dotnet.exe is {0}", currentProcessFileName); + TPDebug.Assert(dataCollectorDirectory is not null, "dataCollectorDirectory is null"); var dataCollectorAssemblyPath = Path.Combine(dataCollectorDirectory, DataCollectorProcessName); - string dataCollectorFileName = Path.GetFileNameWithoutExtension(dataCollectorAssemblyPath); var args = "exec"; @@ -101,10 +96,17 @@ public override int LaunchDataCollector(IDictionary environmentV EqtTrace.Verbose("DotnetDataCollectionLauncher: File {0}, does not exist", depsFilePath); } + var currentProcessFileName = _processHelper.GetCurrentProcessFileName(); + TPDebug.Assert(currentProcessFileName is not null, "currentProcessFileName is null"); + EqtTrace.Verbose("DotnetDataCollectionLauncher: Full path of dotnet.exe is {0}", currentProcessFileName); + var cliArgs = string.Join(" ", commandLineArguments); var argumentsString = string.Format("{0} \"{1}\" {2} ", args, dataCollectorAssemblyPath, cliArgs); + var dataCollectorProcess = _processHelper.LaunchProcess(currentProcessFileName, argumentsString, Directory.GetCurrentDirectory(), environmentVariables, ErrorReceivedCallback, ExitCallBack, null); + DataCollectorProcessId = _processHelper.GetProcessId(dataCollectorProcess); + return DataCollectorProcessId; } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionExtensionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionExtensionManager.cs index 3dfff93131..27ddd496f7 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionExtensionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionExtensionManager.cs @@ -18,8 +18,6 @@ using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -27,22 +25,19 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// internal class InProcDataCollectionExtensionManager { - internal IDictionary InProcDataCollectors; - - private readonly IDataCollectionSink _inProcDataCollectionSink; - private const string DataCollectorEndsWithPattern = @"Collector.dll"; - private readonly string _defaultCodeBase; - - private readonly List _codeBasePaths; - + private readonly IDataCollectionSink _inProcDataCollectionSink; + private readonly string? _defaultCodeBase; + private readonly List _codeBasePaths; private readonly IFileHelper _fileHelper; + internal IDictionary InProcDataCollectors; + /// /// Loaded in-proc datacollectors collection /// - private IEnumerable _inProcDataCollectorSettingsCollection; + private IEnumerable? _inProcDataCollectorSettingsCollection; /// /// Initializes a new instance of the class. @@ -56,23 +51,23 @@ internal class InProcDataCollectionExtensionManager /// /// The default code base to be used by in-proc data collector /// - public InProcDataCollectionExtensionManager(string runSettings, ITestEventsPublisher testEventsPublisher, string defaultCodeBase, TestPluginCache testPluginCache) + public InProcDataCollectionExtensionManager(string? runSettings, ITestEventsPublisher testEventsPublisher, string? defaultCodeBase, TestPluginCache testPluginCache) : this(runSettings, testEventsPublisher, defaultCodeBase, testPluginCache, new FileHelper()) { } - protected InProcDataCollectionExtensionManager(string runSettings, ITestEventsPublisher testEventsPublisher, string defaultCodeBase, TestPluginCache testPluginCache, IFileHelper fileHelper) + protected InProcDataCollectionExtensionManager(string? runSettings, ITestEventsPublisher testEventsPublisher, string? defaultCodeBase, TestPluginCache testPluginCache, IFileHelper fileHelper) { InProcDataCollectors = new Dictionary(); _inProcDataCollectionSink = new InProcDataCollectionSink(); _defaultCodeBase = defaultCodeBase; _fileHelper = fileHelper; - _codeBasePaths = new List { _defaultCodeBase }; + _codeBasePaths = new List { _defaultCodeBase }; // Get Datacollector code base paths from test plugin cache var extensionPaths = testPluginCache.GetExtensionPaths(DataCollectorEndsWithPattern); foreach (var extensionPath in extensionPaths) { - _codeBasePaths.Add(Path.GetDirectoryName(extensionPath)); + _codeBasePaths.Add(Path.GetDirectoryName(extensionPath)!); } // Initialize InProcDataCollectors @@ -127,7 +122,7 @@ protected virtual IInProcDataCollector CreateDataCollector(string assemblyQualif /// /// The e. /// - private void TriggerTestSessionStart(object sender, SessionStartEventArgs e) + private void TriggerTestSessionStart(object? sender, SessionStartEventArgs e) { TestSessionStartArgs testSessionStartArgs = new(GetSessionStartProperties(e)); TriggerInProcDataCollectionMethods(Constants.TestSessionStartMethodName, testSessionStartArgs); @@ -142,7 +137,7 @@ private void TriggerTestSessionStart(object sender, SessionStartEventArgs e) /// /// The e. /// - private void TriggerTestSessionEnd(object sender, SessionEndEventArgs e) + private void TriggerTestSessionEnd(object? sender, SessionEndEventArgs e) { var testSessionEndArgs = new TestSessionEndArgs(); TriggerInProcDataCollectionMethods(Constants.TestSessionEndMethodName, testSessionEndArgs); @@ -157,7 +152,7 @@ private void TriggerTestSessionEnd(object sender, SessionEndEventArgs e) /// /// The e. /// - private void TriggerTestCaseStart(object sender, TestCaseStartEventArgs e) + private void TriggerTestCaseStart(object? sender, TestCaseStartEventArgs e) { var testCaseStartArgs = new TestCaseStartArgs(e.TestElement); TriggerInProcDataCollectionMethods(Constants.TestCaseStartMethodName, testCaseStartArgs); @@ -172,7 +167,7 @@ private void TriggerTestCaseStart(object sender, TestCaseStartEventArgs e) /// /// The e. /// - private void TriggerTestCaseEnd(object sender, TestCaseEndEventArgs e) + private void TriggerTestCaseEnd(object? sender, TestCaseEndEventArgs e) { var dataCollectionContext = new DataCollectionContext(e.TestElement); var testCaseEndArgs = new TestCaseEndArgs(dataCollectionContext, e.TestOutcome); @@ -188,7 +183,7 @@ private void TriggerTestCaseEnd(object sender, TestCaseEndEventArgs e) /// /// The e. /// - private void TriggerUpdateTestResult(object sender, TestResultEventArgs e) + private void TriggerUpdateTestResult(object? sender, TestResultEventArgs e) { // Just set the cached in-proc data if already exists SetInProcDataCollectionDataInTestResult(e.TestResult); @@ -200,7 +195,7 @@ private void TriggerUpdateTestResult(object sender, TestResultEventArgs e) /// /// The run Settings. /// - private void InitializeInProcDataCollectors(string runSettings) + private void InitializeInProcDataCollectors(string? runSettings) { try { @@ -210,22 +205,24 @@ private void InitializeInProcDataCollectors(string runSettings) // Verify if it has any valid in-proc datacollectors or just a dummy element inProcDataCollectionSettingsPresentInRunSettings = inProcDataCollectionSettingsPresentInRunSettings && - inProcDataCollectionRunSettings.DataCollectorSettingsList.Any(); + inProcDataCollectionRunSettings!.DataCollectorSettingsList.Any(); // Initialize if we have at least one - if (inProcDataCollectionSettingsPresentInRunSettings) + if (!inProcDataCollectionSettingsPresentInRunSettings) { - _inProcDataCollectorSettingsCollection = inProcDataCollectionRunSettings.DataCollectorSettingsList; - - var interfaceTypeInfo = typeof(InProcDataCollection).GetTypeInfo(); - foreach (var inProcDc in _inProcDataCollectorSettingsCollection) - { - var codeBase = GetCodebase(inProcDc.CodeBase); - var assemblyQualifiedName = inProcDc.AssemblyQualifiedName; - var configuration = inProcDc.Configuration; - var inProcDataCollector = CreateDataCollector(assemblyQualifiedName, codeBase, configuration, interfaceTypeInfo); - InProcDataCollectors[inProcDataCollector.AssemblyQualifiedName] = inProcDataCollector; - } + return; + } + + _inProcDataCollectorSettingsCollection = inProcDataCollectionRunSettings!.DataCollectorSettingsList; + + var interfaceTypeInfo = typeof(InProcDataCollection).GetTypeInfo(); + foreach (var inProcDc in _inProcDataCollectorSettingsCollection) + { + var codeBase = GetCodebase(inProcDc.CodeBase); + var assemblyQualifiedName = inProcDc.AssemblyQualifiedName; + var configuration = inProcDc.Configuration; + var inProcDataCollector = CreateDataCollector(assemblyQualifiedName, codeBase, configuration, interfaceTypeInfo); + InProcDataCollectors[inProcDataCollector.AssemblyQualifiedName!] = inProcDataCollector; } } catch (Exception ex) @@ -246,22 +243,29 @@ private void InitializeInProcDataCollectors(string runSettings) /// Code base private string GetCodebase(string codeBase) { - if (!Path.IsPathRooted(codeBase)) + if (Path.IsPathRooted(codeBase)) + { + return codeBase; + } + + foreach (var extensionPath in _codeBasePaths) { - foreach (var extensionPath in _codeBasePaths) + if (extensionPath is null) + { + continue; + } + + var assemblyPath = Path.Combine(extensionPath, codeBase); + if (_fileHelper.Exists(assemblyPath)) { - var assemblyPath = Path.Combine(extensionPath, codeBase); - if (_fileHelper.Exists(assemblyPath)) - { - return assemblyPath; - } + return assemblyPath; } } return codeBase; } - private IDictionary GetSessionStartProperties(SessionStartEventArgs sessionStartEventArgs) + private static IDictionary GetSessionStartProperties(SessionStartEventArgs sessionStartEventArgs) { var properties = new Dictionary { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionSink.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionSink.cs index 8f27587f88..17fb22dd03 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionSink.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollectionSink.cs @@ -7,8 +7,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; // internal class InProcDataCollectionSink : IDataCollectionSink @@ -41,8 +39,7 @@ public void SendData(DataCollectionContext dataCollectionContext, string key, st /// test data collection dictionary public IDictionary GetDataCollectionDataSetForTestCase(Guid testCaseId) { - - if (!_testCaseDataCollectionDataMap.TryGetValue(testCaseId, out TestCaseDataCollectionData testCaseDataCollection)) + if (!_testCaseDataCollectionDataMap.TryGetValue(testCaseId, out TestCaseDataCollectionData? testCaseDataCollection)) { EqtTrace.Warning("No DataCollection Data set for the test case {0}", testCaseId); return new Dictionary(); diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollector.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollector.cs index 5888c6ac07..43dd5cff7e 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollector.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/InProcDataCollector.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; @@ -15,8 +14,6 @@ using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -27,17 +24,17 @@ internal class InProcDataCollector : IInProcDataCollector /// /// DataCollector Class Type /// - private readonly Type _dataCollectorType; + private readonly Type? _dataCollectorType; /// /// Instance of the /// - private object _dataCollectorObject; + private object? _dataCollectorObject; /// /// Config XML from the runsettings for current datacollector /// - private readonly string _configXml; + private readonly string? _configXml; /// /// AssemblyLoadContext for current platform @@ -48,7 +45,7 @@ public InProcDataCollector( string codeBase, string assemblyQualifiedName, TypeInfo interfaceTypeInfo, - string configXml) + string? configXml) : this(codeBase, assemblyQualifiedName, interfaceTypeInfo, configXml, new PlatformAssemblyLoadContext(), TestPluginCache.Instance) { } @@ -66,7 +63,7 @@ public InProcDataCollector( /// /// /// - internal InProcDataCollector(string codeBase, string assemblyQualifiedName, TypeInfo interfaceTypeInfo, string configXml, IAssemblyLoadContext assemblyLoadContext, TestPluginCache testPluginCache) + internal InProcDataCollector(string codeBase, string assemblyQualifiedName, TypeInfo interfaceTypeInfo, string? configXml, IAssemblyLoadContext assemblyLoadContext, TestPluginCache testPluginCache) { _configXml = configXml; _assemblyLoadContext = assemblyLoadContext; @@ -78,15 +75,15 @@ internal InProcDataCollector(string codeBase, string assemblyQualifiedName, Type { // If we're loading coverlet collector we skip to check the version of assembly // to allow upgrade through nuget package - filterPredicate = (x) => x.FullName.Equals(Constants.CoverletDataCollectorTypeName) && interfaceTypeInfo.IsAssignableFrom(x.GetTypeInfo()); + filterPredicate = x => Constants.CoverletDataCollectorTypeName.Equals(x.FullName) && interfaceTypeInfo.IsAssignableFrom(x.GetTypeInfo()); // Coverlet collector is consumed as nuget package we need to add assemblies directory to resolver to correctly load references. - Debug.Assert(Path.IsPathRooted(codeBase), "Absolute path expected"); - testPluginCache.AddResolverSearchDirectories(new string[] { Path.GetDirectoryName(codeBase) }); + TPDebug.Assert(Path.IsPathRooted(codeBase), "Absolute path expected"); + testPluginCache.AddResolverSearchDirectories(new string[] { Path.GetDirectoryName(codeBase)! }); } else { - filterPredicate = (x) => x.AssemblyQualifiedName.Equals(assemblyQualifiedName) && interfaceTypeInfo.IsAssignableFrom(x.GetTypeInfo()); + filterPredicate = x => string.Equals(x.AssemblyQualifiedName, assemblyQualifiedName) && interfaceTypeInfo.IsAssignableFrom(x.GetTypeInfo()); } _dataCollectorType = assembly?.GetTypes().FirstOrDefault(filterPredicate); @@ -96,7 +93,7 @@ internal InProcDataCollector(string codeBase, string assemblyQualifiedName, Type /// /// AssemblyQualifiedName of the datacollector type /// - public string AssemblyQualifiedName { get; private set; } + public string? AssemblyQualifiedName { get; private set; } /// /// Loads the DataCollector type @@ -115,7 +112,7 @@ public void LoadDataCollector(IDataCollectionSink inProcDataCollectionSink) /// Arguments for the method public void TriggerInProcDataCollectionMethod(string methodName, InProcDataCollectionArgs methodArg) { - var methodInfo = GetMethodInfoFromType(_dataCollectorObject.GetType(), methodName, new[] { methodArg.GetType() }); + var methodInfo = GetMethodInfoFromType(_dataCollectorObject?.GetType(), methodName, new[] { methodArg.GetType() }); if (methodName.Equals(Constants.TestSessionStartMethodName)) { @@ -129,21 +126,21 @@ public void TriggerInProcDataCollectionMethod(string methodName, InProcDataColle } } - private void InitializeDataCollector(object obj, IDataCollectionSink inProcDataCollectionSink) + private static void InitializeDataCollector(object? obj, IDataCollectionSink inProcDataCollectionSink) { - var initializeMethodInfo = GetMethodInfoFromType(obj.GetType(), "Initialize", new Type[] { typeof(IDataCollectionSink) }); - initializeMethodInfo.Invoke(obj, new object[] { inProcDataCollectionSink }); + var initializeMethodInfo = GetMethodInfoFromType(obj?.GetType(), "Initialize", new Type[] { typeof(IDataCollectionSink) }); + initializeMethodInfo?.Invoke(obj, new object[] { inProcDataCollectionSink }); } - private static MethodInfo GetMethodInfoFromType(Type type, string funcName, Type[] argumentTypes) + private static MethodInfo? GetMethodInfoFromType(Type? type, string funcName, Type[] argumentTypes) { - return type.GetMethod(funcName, argumentTypes); + return type?.GetMethod(funcName, argumentTypes); } - private static object CreateObjectFromType(Type type) + private static object? CreateObjectFromType(Type? type) { - var constructorInfo = type.GetConstructor(Type.EmptyTypes); - object obj = constructorInfo?.Invoke(new object[] { }); + var constructorInfo = type?.GetConstructor(Type.EmptyTypes); + object? obj = constructorInfo?.Invoke(new object[] { }); return obj; } @@ -152,9 +149,9 @@ private static object CreateObjectFromType(Type type) /// /// /// - private Assembly LoadInProcDataCollectorExtension(string codeBase) + private Assembly? LoadInProcDataCollectorExtension(string codeBase) { - Assembly assembly = null; + Assembly? assembly = null; try { assembly = _assemblyLoadContext.LoadAssemblyFromPath(Environment.ExpandEnvironmentVariables(codeBase)); diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IDataCollectionLauncher.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IDataCollectionLauncher.cs index e00b6ce877..a13b40ebb3 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IDataCollectionLauncher.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IDataCollectionLauncher.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces; /// @@ -29,5 +27,5 @@ internal interface IDataCollectionLauncher /// /// The . /// - int LaunchDataCollector(IDictionary environmentVariables, IList commandLineArguments); + int LaunchDataCollector(IDictionary? environmentVariables, IList commandLineArguments); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IDataCollectorsSettingsProvider.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IDataCollectorsSettingsProvider.cs index 1d90aab219..f8b5c93d2d 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IDataCollectorsSettingsProvider.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IDataCollectorsSettingsProvider.cs @@ -4,8 +4,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces; /// diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IInProcDataCollector.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IInProcDataCollector.cs index 0ceb4785e5..ed34328304 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IInProcDataCollector.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IInProcDataCollector.cs @@ -4,8 +4,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollector.InProcDataCollector; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces; internal interface IInProcDataCollector @@ -13,7 +11,7 @@ internal interface IInProcDataCollector /// /// AssemblyQualifiedName of the datacollector type /// - string AssemblyQualifiedName { get; } + string? AssemblyQualifiedName { get; } /// /// Loads the DataCollector type diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IProxyDataCollectionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IProxyDataCollectionManager.cs index 6c61124940..09cf462c27 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IProxyDataCollectionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/IProxyDataCollectionManager.cs @@ -6,8 +6,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces; /// @@ -23,7 +21,7 @@ public interface IProxyDataCollectionManager : IDisposable /// /// The settings xml /// - string SettingsXml { get; } + string? SettingsXml { get; } /// /// List of test sources diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/ITestEventsPublisher.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/ITestEventsPublisher.cs index c2bd8ead77..f7ef97c58a 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/ITestEventsPublisher.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/Interfaces/ITestEventsPublisher.cs @@ -5,8 +5,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection.Interfaces; /// diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ParallelDataCollectionEventsHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ParallelDataCollectionEventsHandler.cs index 63975ac816..538e6c0ceb 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ParallelDataCollectionEventsHandler.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ParallelDataCollectionEventsHandler.cs @@ -11,14 +11,12 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; internal class ParallelDataCollectionEventsHandler : ParallelRunEventsHandler { private readonly ParallelRunDataAggregator _runDataAggregator; - private readonly ITestRunAttachmentsProcessingManager _attachmentsProcessingManager; + private readonly ITestRunAttachmentsProcessingManager? _attachmentsProcessingManager; private readonly CancellationToken _cancellationToken; public ParallelDataCollectionEventsHandler(IRequestData requestData, @@ -27,8 +25,8 @@ public ParallelDataCollectionEventsHandler(IRequestData requestData, IParallelProxyExecutionManager parallelProxyExecutionManager, ParallelRunDataAggregator runDataAggregator, ITestRunAttachmentsProcessingManager attachmentsProcessingManager, - CancellationToken cancellationToken) : - this(requestData, proxyExecutionManager, actualRunEventsHandler, parallelProxyExecutionManager, runDataAggregator, JsonDataSerializer.Instance) + CancellationToken cancellationToken) + : this(requestData, proxyExecutionManager, actualRunEventsHandler, parallelProxyExecutionManager, runDataAggregator, JsonDataSerializer.Instance) { _attachmentsProcessingManager = attachmentsProcessingManager; _cancellationToken = cancellationToken; @@ -39,8 +37,8 @@ internal ParallelDataCollectionEventsHandler(IRequestData requestData, IInternalTestRunEventsHandler actualRunEventsHandler, IParallelProxyExecutionManager parallelProxyExecutionManager, ParallelRunDataAggregator runDataAggregator, - IDataSerializer dataSerializer) : - base(requestData, proxyExecutionManager, actualRunEventsHandler, parallelProxyExecutionManager, runDataAggregator, dataSerializer) + IDataSerializer dataSerializer) + : base(requestData, proxyExecutionManager, actualRunEventsHandler, parallelProxyExecutionManager, runDataAggregator, dataSerializer) { _runDataAggregator = runDataAggregator; } @@ -50,28 +48,31 @@ internal ParallelDataCollectionEventsHandler(IRequestData requestData, /// public override void HandleTestRunComplete( TestRunCompleteEventArgs testRunCompleteArgs, - TestRunChangedEventArgs lastChunkArgs, - ICollection runContextAttachments, - ICollection executorUris) + TestRunChangedEventArgs? lastChunkArgs, + ICollection? runContextAttachments, + ICollection? executorUris) { var parallelRunComplete = HandleSingleTestRunComplete(testRunCompleteArgs, lastChunkArgs, runContextAttachments, executorUris); - if (parallelRunComplete) + if (!parallelRunComplete) { - _runDataAggregator.RunContextAttachments = _attachmentsProcessingManager.ProcessTestRunAttachmentsAsync(_runDataAggregator.RunSettings, _requestData, _runDataAggregator.RunContextAttachments, _runDataAggregator.InvokedDataCollectors, _cancellationToken).Result ?? _runDataAggregator.RunContextAttachments; + return; + } - var completedArgs = new TestRunCompleteEventArgs(_runDataAggregator.GetAggregatedRunStats(), - _runDataAggregator.IsCanceled, - _runDataAggregator.IsAborted, - _runDataAggregator.GetAggregatedException(), - _runDataAggregator.RunContextAttachments, - _runDataAggregator.InvokedDataCollectors, - _runDataAggregator.ElapsedTime); + TPDebug.Assert(_attachmentsProcessingManager is not null, "_attachmentsProcessingManager is null"); + _runDataAggregator.RunContextAttachments = _attachmentsProcessingManager.ProcessTestRunAttachmentsAsync(_runDataAggregator.RunSettings, _requestData, _runDataAggregator.RunContextAttachments, _runDataAggregator.InvokedDataCollectors, _cancellationToken).Result ?? _runDataAggregator.RunContextAttachments; - // Add Metrics from Test Host - completedArgs.Metrics = _runDataAggregator.GetAggregatedRunDataMetrics(); + var completedArgs = new TestRunCompleteEventArgs(_runDataAggregator.GetAggregatedRunStats(), + _runDataAggregator.IsCanceled, + _runDataAggregator.IsAborted, + _runDataAggregator.GetAggregatedException(), + _runDataAggregator.RunContextAttachments, + _runDataAggregator.InvokedDataCollectors, + _runDataAggregator.ElapsedTime); - HandleParallelTestRunComplete(completedArgs); - } + // Add Metrics from Test Host + completedArgs.Metrics = _runDataAggregator.GetAggregatedRunDataMetrics(); + + HandleParallelTestRunComplete(completedArgs); } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyDataCollectionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyDataCollectionManager.cs index 0fc077c1eb..f34712c309 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyDataCollectionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyDataCollectionManager.cs @@ -29,8 +29,6 @@ using CoreUtilitiesConstants = Microsoft.VisualStudio.TestPlatform.CoreUtilities.Constants; using CrossPlatEngineResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -54,7 +52,7 @@ internal class ProxyDataCollectionManager : IProxyDataCollectionManager /// /// The settings xml /// - public string SettingsXml { get; } + public string? SettingsXml { get; } /// /// List of test sources @@ -73,7 +71,7 @@ internal class ProxyDataCollectionManager : IProxyDataCollectionManager /// /// Test Run sources /// - public ProxyDataCollectionManager(IRequestData requestData, string settingsXml, IEnumerable sources) + public ProxyDataCollectionManager(IRequestData requestData, string? settingsXml, IEnumerable sources) : this(requestData, settingsXml, sources, new ProcessHelper()) { } @@ -93,7 +91,8 @@ public ProxyDataCollectionManager(IRequestData requestData, string settingsXml, /// /// The process helper. /// - internal ProxyDataCollectionManager(IRequestData requestData, string settingsXml, IEnumerable sources, IProcessHelper processHelper) : this(requestData, settingsXml, sources, new DataCollectionRequestSender(), processHelper, DataCollectionLauncherFactory.GetDataCollectorLauncher(processHelper, settingsXml)) + internal ProxyDataCollectionManager(IRequestData requestData, string? settingsXml, IEnumerable sources, IProcessHelper processHelper) + : this(requestData, settingsXml, sources, new DataCollectionRequestSender(), processHelper, DataCollectionLauncherFactory.GetDataCollectorLauncher(processHelper, settingsXml)) { } @@ -118,7 +117,7 @@ public ProxyDataCollectionManager(IRequestData requestData, string settingsXml, /// /// Launches datacollector process. /// - internal ProxyDataCollectionManager(IRequestData requestData, string settingsXml, + internal ProxyDataCollectionManager(IRequestData requestData, string? settingsXml, IEnumerable sources, IDataCollectionRequestSender dataCollectionRequestSender, IProcessHelper processHelper, IDataCollectionLauncher dataCollectionLauncher) @@ -147,9 +146,9 @@ internal ProxyDataCollectionManager(IRequestData requestData, string settingsXml /// /// The . /// - public DataCollectionResult AfterTestRunEnd(bool isCanceled, ITestMessageEventHandler runEventsHandler) + public DataCollectionResult AfterTestRunEnd(bool isCanceled, ITestMessageEventHandler? runEventsHandler) { - AfterTestRunEndResult afterTestRunEnd = null; + AfterTestRunEndResult? afterTestRunEnd = null; InvokeDataCollectionServiceAction( () => { @@ -187,7 +186,7 @@ public DataCollectionResult AfterTestRunEnd(bool isCanceled, ITestMessageEventHa public DataCollectionParameters BeforeTestRunStart( bool resetDataCollectors, bool isRunStartingNow, - ITestMessageEventHandler runEventsHandler) + ITestMessageEventHandler? runEventsHandler) { var areTestCaseLevelEventsRequired = false; IDictionary environmentVariables = new Dictionary(); @@ -198,6 +197,7 @@ public DataCollectionParameters BeforeTestRunStart( { EqtTrace.Info("ProxyDataCollectionManager.BeforeTestRunStart: Get environment variable and port for datacollector processId: {0} port: {1}", _dataCollectionProcessId, _dataCollectionPort); var result = _dataCollectionRequestSender.SendBeforeTestRunStartAndGetResult(SettingsXml, Sources, _requestData.IsTelemetryOptedIn, runEventsHandler); + TPDebug.Assert(result is not null, "result is null"); environmentVariables = result.EnvironmentVariables; dataCollectionEventsPort = result.DataCollectionEventsPort; @@ -266,7 +266,7 @@ private int GetConnectionTimeout(int processId) // Increase connection timeout when debugging is enabled. var dataCollectorDebugEnabled = Environment.GetEnvironmentVariable(DebugEnvironmentVaribleName); - if (!string.IsNullOrEmpty(dataCollectorDebugEnabled) && + if (!StringUtils.IsNullOrEmpty(dataCollectorDebugEnabled) && dataCollectorDebugEnabled.Equals("1", StringComparison.Ordinal)) { ConsoleOutput.Instance.WriteLine(CrossPlatEngineResources.DataCollectorDebuggerWarning, OutputLevel.Warning); @@ -281,7 +281,7 @@ private int GetConnectionTimeout(int processId) return connectionTimeout; } - private void InvokeDataCollectionServiceAction(Action action, ITestMessageEventHandler runEventsHandler) + private void InvokeDataCollectionServiceAction(Action action, ITestMessageEventHandler? runEventsHandler) { try { @@ -296,10 +296,10 @@ private void InvokeDataCollectionServiceAction(Action action, ITestMessageEventH } } - private void HandleExceptionMessage(ITestMessageEventHandler runEventsHandler, Exception exception) + private static void HandleExceptionMessage(ITestMessageEventHandler? runEventsHandler, Exception exception) { EqtTrace.Error(exception); - runEventsHandler.HandleLogMessage(ObjectModel.Logging.TestMessageLevel.Error, exception.ToString()); + runEventsHandler?.HandleLogMessage(ObjectModel.Logging.TestMessageLevel.Error, exception.ToString()); } private IList GetCommandLineArguments(int portNumber) @@ -313,7 +313,7 @@ private IList GetCommandLineArguments(int portNumber) _processHelper.GetCurrentProcessId().ToString() }; - if (!string.IsNullOrEmpty(EqtTrace.LogFile)) + if (!StringUtils.IsNullOrEmpty(EqtTrace.LogFile)) { commandlineArguments.Add(DiagOption); commandlineArguments.Add(GetTimestampedLogFile(EqtTrace.LogFile)); @@ -325,7 +325,7 @@ private IList GetCommandLineArguments(int portNumber) return commandlineArguments; } - private string GetTimestampedLogFile(string logFile) + private static string GetTimestampedLogFile(string logFile) { return Path.ChangeExtension( logFile, @@ -340,14 +340,14 @@ private string GetTimestampedLogFile(string logFile) /// Update Extensions path folder in test adapters paths in runsettings. /// /// - private static string UpdateExtensionsFolderInRunSettings(string settingsXml) + private static string? UpdateExtensionsFolderInRunSettings(string? settingsXml) { - if (string.IsNullOrWhiteSpace(settingsXml)) + if (settingsXml.IsNullOrWhiteSpace()) { return settingsXml; } - var extensionsFolder = Path.Combine(Path.GetDirectoryName(typeof(ITestPlatform).GetTypeInfo().Assembly.GetAssemblyLocation()), "Extensions"); + var extensionsFolder = Path.Combine(Path.GetDirectoryName(typeof(ITestPlatform).GetTypeInfo().Assembly.GetAssemblyLocation())!, "Extensions"); using var stream = new StringReader(settingsXml); using var reader = XmlReader.Create(stream, XmlRunSettingsUtilities.ReaderSettings); @@ -356,7 +356,7 @@ private static string UpdateExtensionsFolderInRunSettings(string settingsXml) var tapNode = RunSettingsProviderExtensions.GetXmlNode(document, "RunConfiguration.TestAdaptersPaths"); - if (tapNode != null && !string.IsNullOrWhiteSpace(tapNode.InnerText)) + if (tapNode != null && !StringUtils.IsNullOrWhiteSpace(tapNode.InnerText)) { extensionsFolder = string.Concat(tapNode.InnerText, ';', extensionsFolder); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyOutOfProcDataCollectionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyOutOfProcDataCollectionManager.cs index de66c8cac7..8ae2a30f3c 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyOutOfProcDataCollectionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyOutOfProcDataCollectionManager.cs @@ -10,8 +10,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection; /// @@ -50,12 +48,12 @@ public ProxyOutOfProcDataCollectionManager(IDataCollectionTestCaseEventSender da _attachmentsCache = new Dictionary>(); } - private void TriggerTestCaseStart(object sender, TestCaseStartEventArgs e) + private void TriggerTestCaseStart(object? sender, TestCaseStartEventArgs e) { _dataCollectionTestCaseEventSender.SendTestCaseStart(e); } - private void TriggerTestCaseEnd(object sender, TestCaseEndEventArgs e) + private void TriggerTestCaseEnd(object? sender, TestCaseEndEventArgs e) { var attachments = _dataCollectionTestCaseEventSender.SendTestCaseEnd(e); @@ -63,7 +61,7 @@ private void TriggerTestCaseEnd(object sender, TestCaseEndEventArgs e) { lock (_syncObject) { - if (!_attachmentsCache.TryGetValue(e.TestCaseId, out Collection attachmentSets)) + if (!_attachmentsCache.TryGetValue(e.TestCaseId, out Collection? attachmentSets)) { attachmentSets = new Collection(); _attachmentsCache.Add(e.TestCaseId, attachmentSets); @@ -77,11 +75,11 @@ private void TriggerTestCaseEnd(object sender, TestCaseEndEventArgs e) } } - private void TriggerSendTestResult(object sender, TestResultEventArgs e) + private void TriggerSendTestResult(object? sender, TestResultEventArgs e) { lock (_syncObject) { - if (_attachmentsCache.TryGetValue(e.TestCaseId, out Collection attachmentSets)) + if (_attachmentsCache.TryGetValue(e.TestCaseId, out Collection? attachmentSets)) { foreach (var attachment in attachmentSets) { @@ -93,7 +91,7 @@ private void TriggerSendTestResult(object sender, TestResultEventArgs e) } } - private void TriggerTestSessionEnd(object sender, SessionEndEventArgs e) + private void TriggerTestSessionEnd(object? sender, SessionEndEventArgs e) { _dataCollectionTestCaseEventSender.SendTestSessionEnd(e); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscovererEnumerator.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscovererEnumerator.cs index d469ca6431..a774a90433 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscovererEnumerator.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscovererEnumerator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; @@ -27,8 +28,6 @@ using CrossPlatEngineResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Discovery; /// @@ -96,7 +95,7 @@ public DiscovererEnumerator(IRequestData requestData, /// The settings. /// The test case filter. /// The logger. - public void LoadTests(IDictionary> testExtensionSourceMap, IRunSettings settings, string testCaseFilter, IMessageLogger logger) + public void LoadTests(IDictionary> testExtensionSourceMap, IRunSettings settings, string? testCaseFilter, IMessageLogger logger) { _testPlatformEventSource.DiscoveryStart(); try @@ -122,7 +121,7 @@ public void LoadTests(IDictionary> testExtensionSour /// The settings. /// The test case filter. /// The logger. - private void LoadTestsFromAnExtension(string extensionAssembly, IEnumerable sources, IRunSettings settings, string testCaseFilter, IMessageLogger logger) + private void LoadTestsFromAnExtension(string extensionAssembly, IEnumerable sources, IRunSettings settings, string? testCaseFilter, IMessageLogger logger) { // Stopwatch to collect metrics var timeStart = DateTime.UtcNow; @@ -147,7 +146,7 @@ private void LoadTestsFromAnExtension(string extensionAssembly, IEnumerable discoverer, IMessageLogger logger, out Type discovererType) + private static bool TryToLoadDiscoverer(LazyExtension discoverer, IMessageLogger logger, [NotNullWhen(true)] out Type? discovererType) { discovererType = null; @@ -302,16 +301,16 @@ private static bool IsDiscovererFromDeprecatedLocations( var discovererLocation = discoverer.Value.GetType().GetTypeInfo().Assembly.GetAssemblyLocation(); - return Path.GetDirectoryName(discovererLocation) + return Path.GetDirectoryName(discovererLocation)! .Equals(CrossPlatEngine.Constants.DefaultAdapterLocation, StringComparison.OrdinalIgnoreCase); } - private static void LogWarningOnNoTestsDiscovered(IEnumerable sources, string testCaseFilter, IMessageLogger logger) + private static void LogWarningOnNoTestsDiscovered(IEnumerable sources, string? testCaseFilter, IMessageLogger logger) { var sourcesString = string.Join(" ", sources); // Print warning on no tests. - if (!string.IsNullOrEmpty(testCaseFilter)) + if (!testCaseFilter.IsNullOrEmpty()) { var testCaseFilterToShow = TestCaseFilterDeterminer.ShortenTestCaseFilterIfRequired(testCaseFilter); @@ -355,7 +354,7 @@ private void SetAdapterLoggingSettings(IMessageLogger messageLogger, IRunSetting /// The sources. /// The logger instance. /// The map between an extension type and a source. - internal static Dictionary, IEnumerable> GetDiscovererToSourcesMap( + internal static Dictionary, IEnumerable>? GetDiscovererToSourcesMap( string extensionAssembly, IEnumerable sources, IMessageLogger logger, @@ -374,7 +373,7 @@ internal static Dictionary> assemblyTypeToSoucesMap = null; + IDictionary>? assemblyTypeToSoucesMap = null; var result = new Dictionary, IEnumerable>(); var sourcesForWhichNoDiscovererIsAvailable = new List(sources); @@ -465,13 +464,13 @@ private static bool IsAssembly(string filePath) ".exe".Equals(fileExtension, StringComparison.OrdinalIgnoreCase); } - private static IEnumerable> GetDiscoverers( + private static IEnumerable>? GetDiscoverers( string extensionAssembly, bool throwOnError) { try { - if (string.IsNullOrEmpty(extensionAssembly) || string.Equals(extensionAssembly, ObjectModel.Constants.UnspecifiedAdapterPath)) + if (StringUtils.IsNullOrEmpty(extensionAssembly) || string.Equals(extensionAssembly, ObjectModel.Constants.UnspecifiedAdapterPath)) { // full discovery. return TestDiscoveryExtensionManager.Create().Discoverers; diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryContext.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryContext.cs index 792b455e5f..e15486609d 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryContext.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryContext.cs @@ -12,8 +12,6 @@ using CrossPlatEngineResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Discovery; /// @@ -24,7 +22,7 @@ public class DiscoveryContext : IDiscoveryContext /// /// Gets the run settings specified for this request. /// - public IRunSettings RunSettings { get; internal set; } + public IRunSettings? RunSettings { get; internal set; } /// /// Returns TestCaseFilterExpression validated for supportedProperties. @@ -33,28 +31,30 @@ public class DiscoveryContext : IDiscoveryContext /// The supported Properties. /// The property Provider. /// The . - public ITestCaseFilterExpression GetTestCaseFilter(IEnumerable supportedProperties, Func propertyProvider) + public ITestCaseFilterExpression? GetTestCaseFilter(IEnumerable? supportedProperties, Func propertyProvider) { - TestCaseFilterExpression adapterSpecificTestCaseFilter = null; - if (FilterExpressionWrapper != null) + TestCaseFilterExpression? adapterSpecificTestCaseFilter = null; + if (FilterExpressionWrapper == null) + { + return adapterSpecificTestCaseFilter; + } + + if (!StringUtils.IsNullOrEmpty(FilterExpressionWrapper.ParseError)) { - if (!string.IsNullOrEmpty(FilterExpressionWrapper.ParseError)) - { - throw new TestPlatformFormatException(FilterExpressionWrapper.ParseError, FilterExpressionWrapper.FilterString); - } + throw new TestPlatformFormatException(FilterExpressionWrapper.ParseError, FilterExpressionWrapper.FilterString); + } - adapterSpecificTestCaseFilter = new TestCaseFilterExpression(FilterExpressionWrapper); - var invalidProperties = adapterSpecificTestCaseFilter.ValidForProperties(supportedProperties, propertyProvider); + adapterSpecificTestCaseFilter = new TestCaseFilterExpression(FilterExpressionWrapper); + var invalidProperties = adapterSpecificTestCaseFilter.ValidForProperties(supportedProperties, propertyProvider); - if (invalidProperties != null) - { - var invalidPropertiesString = string.Join(CrossPlatEngineResources.StringSeperator, invalidProperties); - var validPropertiesSttring = supportedProperties == null ? string.Empty : string.Join(CrossPlatEngineResources.StringSeperator, supportedProperties.ToArray()); - var errorMessage = string.Format(CultureInfo.CurrentCulture, CrossPlatEngineResources.UnsupportedPropertiesInTestCaseFilter, invalidPropertiesString, validPropertiesSttring); + if (invalidProperties != null) + { + var invalidPropertiesString = string.Join(CrossPlatEngineResources.StringSeperator, invalidProperties); + var validPropertiesSttring = supportedProperties == null ? string.Empty : string.Join(CrossPlatEngineResources.StringSeperator, supportedProperties.ToArray()); + var errorMessage = string.Format(CultureInfo.CurrentCulture, CrossPlatEngineResources.UnsupportedPropertiesInTestCaseFilter, invalidPropertiesString, validPropertiesSttring); - // For unsupported property don’t throw exception, just log the message. Later it is going to handle properly with TestCaseFilterExpression.MatchTestCase(). - EqtTrace.Info(errorMessage); - } + // For unsupported property don’t throw exception, just log the message. Later it is going to handle properly with TestCaseFilterExpression.MatchTestCase(). + EqtTrace.Info(errorMessage); } return adapterSpecificTestCaseFilter; @@ -63,5 +63,5 @@ public ITestCaseFilterExpression GetTestCaseFilter(IEnumerable supported /// /// Gets or sets the FilterExpressionWrapper instance as created from filter string. /// - internal FilterExpressionWrapper FilterExpressionWrapper { get; set; } + internal FilterExpressionWrapper? FilterExpressionWrapper { get; set; } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs index d9e426d843..f7e333a6c9 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -24,8 +23,6 @@ using CrossPlatEngineResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Discovery; /// @@ -36,11 +33,12 @@ public class DiscoveryManager : IDiscoveryManager private readonly TestSessionMessageLogger _sessionMessageLogger; private readonly ITestPlatformEventSource _testPlatformEventSource; private readonly IRequestData _requestData; - private ITestDiscoveryEventsHandler2 _testDiscoveryEventsHandler; - private DiscoveryCriteria _discoveryCriteria; private readonly CancellationTokenSource _cancellationTokenSource = new(); private readonly DiscoveryDataAggregator _discoveryDataAggregator = new(); - private string _previousSource; + + private DiscoveryCriteria? _discoveryCriteria; + private ITestDiscoveryEventsHandler2? _testDiscoveryEventsHandler; + private string? _previousSource; /// /// Initializes a new instance of the class. @@ -71,7 +69,7 @@ protected DiscoveryManager(IRequestData requestData, ITestPlatformEventSource te /// Initializes the discovery manager. /// /// The path to additional extensions. - public void Initialize(IEnumerable pathToAdditionalExtensions, ITestDiscoveryEventsHandler2 eventHandler) + public void Initialize(IEnumerable? pathToAdditionalExtensions, ITestDiscoveryEventsHandler2 eventHandler) { // Clear the request data metrics left over from a potential previous run. _requestData.MetricsCollection?.Metrics?.Clear(); @@ -142,7 +140,7 @@ public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEve { if (lastChunk != null) { - UpdateTestCases(lastChunk, _discoveryCriteria.Package); + UpdateTestCases(lastChunk, _discoveryCriteria?.Package); } // Collecting Discovery State @@ -222,7 +220,7 @@ public void Abort(ITestDiscoveryEventsHandler2 eventHandler) private void OnReportTestCases(ICollection testCases) { - UpdateTestCases(testCases, _discoveryCriteria.Package); + UpdateTestCases(testCases, _discoveryCriteria?.Package); if (_testDiscoveryEventsHandler != null) { @@ -242,10 +240,13 @@ private void OnReportTestCases(ICollection testCases) /// logger /// package /// The list of verified sources. - internal static HashSet GetValidSources(IEnumerable sources, IMessageLogger logger, string package) + internal static HashSet GetValidSources(IEnumerable? sources, IMessageLogger logger, string? package) { - Debug.Assert(sources != null, "sources"); var verifiedSources = new HashSet(StringComparer.OrdinalIgnoreCase); + if (sources is null) + { + return verifiedSources; + } foreach (string source in sources) { @@ -260,7 +261,7 @@ void SendWarning() logger.SendMessage(TestMessageLevel.Warning, errorMessage); } - if (string.IsNullOrEmpty(package)) + if (package.IsNullOrEmpty()) { SendWarning(); @@ -268,7 +269,7 @@ void SendWarning() } // It is also possible that this is a packaged app, so the tests might be inside the package - src = !Path.IsPathRooted(source) ? Path.Combine(Path.GetDirectoryName(package), source) : source; + src = !Path.IsPathRooted(source) ? Path.Combine(Path.GetDirectoryName(package)!, source) : source; if (!File.Exists(src)) { @@ -303,7 +304,7 @@ void SendWarning() return verifiedSources; } - private void TestSessionMessageHandler(object sender, TestRunMessageEventArgs e) + private void TestSessionMessageHandler(object? sender, TestRunMessageEventArgs e) { EqtTrace.Info( "TestDiscoveryManager.RunMessage: calling TestRunMessage({0}, {1}) callback.", @@ -322,11 +323,11 @@ private void TestSessionMessageHandler(object sender, TestRunMessageEventArgs e) } } - private static void UpdateTestCases(IEnumerable testCases, string package) + private static void UpdateTestCases(IEnumerable testCases, string? package) { // Update TestCase objects Source data to contain the actual source(package) provided by IDE(users), // else these test cases are not displayed in TestWindow. - if (!string.IsNullOrEmpty(package)) + if (!package.IsNullOrEmpty()) { foreach (var tc in testCases) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryResultCache.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryResultCache.cs index fbf898a7ef..95df0cdd76 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryResultCache.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryResultCache.cs @@ -3,12 +3,9 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using Microsoft.VisualStudio.TestPlatform.ObjectModel; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Discovery; /// @@ -54,9 +51,9 @@ internal class DiscoveryResultCache /// The on report test cases. public DiscoveryResultCache(long cacheSize, TimeSpan discoveredTestEventTimeout, OnReportTestCases onReportTestCases) { - Debug.Assert(cacheSize > 0, "Buffer size cannot be less than zero"); - Debug.Assert(onReportTestCases != null, "Callback which listens for cache size limit cannot be null."); - Debug.Assert(discoveredTestEventTimeout > TimeSpan.MinValue, "The cache timeout must be greater than min value."); + TPDebug.Assert(cacheSize > 0, "Buffer size cannot be less than zero"); + TPDebug.Assert(onReportTestCases != null, "Callback which listens for cache size limit cannot be null."); + TPDebug.Assert(discoveredTestEventTimeout > TimeSpan.MinValue, "The cache timeout must be greater than min value."); _cacheSize = cacheSize; _onReportTestCases = onReportTestCases; @@ -95,7 +92,7 @@ public IList Tests /// The test. public void AddTest(TestCase test) { - Debug.Assert(test != null, "DiscoveryResultCache.AddTest called with no new test."); + TPDebug.Assert(test != null, "DiscoveryResultCache.AddTest called with no new test."); if (test == null) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/TestCaseDiscoverySink.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/TestCaseDiscoverySink.cs index ab4fe14c45..43d5acd7a0 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/TestCaseDiscoverySink.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/TestCaseDiscoverySink.cs @@ -4,8 +4,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Discovery; /// @@ -13,13 +11,13 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Discovery; /// internal class TestCaseDiscoverySink : ITestCaseDiscoverySink { - private readonly DiscoveryResultCache _discoveryRequestCache; + private readonly DiscoveryResultCache? _discoveryRequestCache; /// /// Initializes a new instance of the class. /// /// The discovery request cache. - internal TestCaseDiscoverySink(DiscoveryResultCache discoveryRequestCache) + internal TestCaseDiscoverySink(DiscoveryResultCache? discoveryRequestCache) { _discoveryRequestCache = discoveryRequestCache; } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/IDeploymentAwareTestRequestHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/IDeploymentAwareTestRequestHandler.cs index fce03ff6ff..9c8a8de8a0 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/IDeploymentAwareTestRequestHandler.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/IDeploymentAwareTestRequestHandler.cs @@ -10,6 +10,6 @@ namespace Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; /// internal interface IDeploymentAwareTestRequestHandler { - string LocalPath { get; set; } - string RemotePath { get; set; } -} \ No newline at end of file + string? LocalPath { get; set; } + string? RemotePath { get; set; } +} diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/NullPathConverter.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/NullPathConverter.cs index 29883653e5..6aba702f6c 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/NullPathConverter.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/NullPathConverter.cs @@ -30,9 +30,9 @@ private NullPathConverter() { } TestCase IPathConverter.UpdateTestCase(TestCase testCase, PathConversionDirection _) => testCase; - IEnumerable IPathConverter.UpdateTestCases(IEnumerable testCases, PathConversionDirection _) => testCases; + IEnumerable IPathConverter.UpdateTestCases(IEnumerable? testCases, PathConversionDirection _) => testCases!; - TestRunChangedEventArgs IPathConverter.UpdateTestRunChangedEventArgs(TestRunChangedEventArgs testRunChangedArgs, PathConversionDirection _) => testRunChangedArgs; + TestRunChangedEventArgs IPathConverter.UpdateTestRunChangedEventArgs(TestRunChangedEventArgs? testRunChangedArgs, PathConversionDirection _) => testRunChangedArgs!; TestRunCompleteEventArgs IPathConverter.UpdateTestRunCompleteEventArgs(TestRunCompleteEventArgs testRunCompleteEventArgs, PathConversionDirection _) => testRunCompleteEventArgs; diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestCaseEventsHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestCaseEventsHandler.cs index 9a6eee6c05..42c0213cd0 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestCaseEventsHandler.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestCaseEventsHandler.cs @@ -10,8 +10,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; using Microsoft.VisualStudio.TestPlatform.Utilities; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.EventHandlers; /// @@ -19,15 +17,15 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.EventHandlers; /// internal class TestCaseEventsHandler : ITestCaseEventsHandler, ITestEventsPublisher { - public event EventHandler SessionStart; + public event EventHandler? SessionStart; - public event EventHandler SessionEnd; + public event EventHandler? SessionEnd; - public event EventHandler TestCaseStart; + public event EventHandler? TestCaseStart; - public event EventHandler TestCaseEnd; + public event EventHandler? TestCaseEnd; - public event EventHandler TestResult; + public event EventHandler? TestResult; /// /// Initializes a new instance of the class. diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs index 89a0d0848a..3c54829f76 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs @@ -24,8 +24,6 @@ using CrossPlatResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources; using ObjectModelConstants = Microsoft.VisualStudio.TestPlatform.ObjectModel.Constants; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; /// @@ -34,29 +32,27 @@ namespace Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; /// public class TestRequestHandler : ITestRequestHandler, IDeploymentAwareTestRequestHandler { - private int _protocolVersion = 1; - private readonly int _highestSupportedVersion = ProtocolVersioning.HighestSupportedVersion; - private readonly IDataSerializer _dataSerializer; - private ITestHostManagerFactory _testHostManagerFactory; - private ICommunicationEndPoint _communicationEndPoint; private readonly ICommunicationEndpointFactory _communicationEndpointFactory; - private ICommunicationChannel _channel; - private readonly JobQueue _jobQueue; private readonly IFileHelper _fileHelper; private readonly ManualResetEventSlim _requestSenderConnected; private readonly ManualResetEventSlim _testHostManagerFactoryReady; private readonly ManualResetEventSlim _sessionCompleted; - private Action _onLaunchAdapterProcessWithDebuggerAttachedAckReceived; - private Action _onAttachDebuggerAckRecieved; + + private int _protocolVersion = 1; + private ITestHostManagerFactory? _testHostManagerFactory; + private ICommunicationEndPoint? _communicationEndPoint; + private ICommunicationChannel? _channel; + private Action? _onLaunchAdapterProcessWithDebuggerAttachedAckReceived; + private Action? _onAttachDebuggerAckRecieved; private IPathConverter _pathConverter; - private Exception _messageProcessingUnrecoverableError; + private Exception? _messageProcessingUnrecoverableError; public TestHostConnectionInfo ConnectionInfo { get; set; } - string IDeploymentAwareTestRequestHandler.LocalPath { get; set; } - string IDeploymentAwareTestRequestHandler.RemotePath { get; set; } + string? IDeploymentAwareTestRequestHandler.LocalPath { get; set; } + string? IDeploymentAwareTestRequestHandler.RemotePath { get; set; } public TestRequestHandler() : this(JsonDataSerializer.Instance, new CommunicationEndpointFactory()) { @@ -95,12 +91,12 @@ protected TestRequestHandler(IDataSerializer dataSerializer, ICommunicationEndpo _onAttachDebuggerAckRecieved = (message) => throw new NotImplementedException(); _jobQueue = new JobQueue( - (action) => action(), + action => action?.Invoke(), "TestHostOperationQueue", 500, 25000000, true, - (message) => EqtTrace.Error(message)); + message => EqtTrace.Error(message)); _fileHelper = new FileHelper(); _pathConverter = NullPathConverter.Instance; @@ -111,15 +107,15 @@ public virtual void InitializeCommunication() { if (this is IDeploymentAwareTestRequestHandler self) { - var currentProcessPath = Process.GetCurrentProcess().MainModule.FileName; - var currentProcessDirectory = !string.IsNullOrWhiteSpace(currentProcessPath) + var currentProcessPath = Process.GetCurrentProcess().MainModule?.FileName; + var currentProcessDirectory = !currentProcessPath.IsNullOrWhiteSpace() ? System.IO.Path.GetDirectoryName(currentProcessPath) : null; var remotePath = Environment.GetEnvironmentVariable("VSTEST_UWP_DEPLOY_REMOTE_PATH") ?? self.RemotePath ?? currentProcessDirectory; var localPath = Environment.GetEnvironmentVariable("VSTEST_UWP_DEPLOY_LOCAL_PATH") ?? self.LocalPath; - if (!string.IsNullOrWhiteSpace(localPath) - && !string.IsNullOrWhiteSpace(remotePath)) + if (!localPath.IsNullOrWhiteSpace() + && !remotePath.IsNullOrWhiteSpace()) { _pathConverter = new PathConverter(localPath, remotePath, _fileHelper); } @@ -158,7 +154,7 @@ public void ProcessRequests(ITestHostManagerFactory testHostManagerFactory) /// public void Dispose() { - _communicationEndPoint.Stop(); + _communicationEndPoint?.Stop(); _channel?.Dispose(); } @@ -204,7 +200,9 @@ public void SendExecutionComplete( { // When we abort the run we might have saved the error before we gave the handler the chance to abort // if the handler does not return with any new error we report the original one. - if (testRunCompleteArgs.IsAborted && testRunCompleteArgs.Error == null && _messageProcessingUnrecoverableError != null) + if (testRunCompleteArgs.IsAborted + && testRunCompleteArgs.Error == null + && _messageProcessingUnrecoverableError != null) { var curentArgs = testRunCompleteArgs; testRunCompleteArgs = new TestRunCompleteEventArgs( @@ -229,14 +227,15 @@ public void SendExecutionComplete( } /// - public void DiscoveryComplete(DiscoveryCompleteEventArgs discoveryCompleteEventArgs, IEnumerable lastChunk) + public void DiscoveryComplete(DiscoveryCompleteEventArgs discoveryCompleteEventArgs, IEnumerable? lastChunk) { var data = _dataSerializer.SerializePayload( MessageType.DiscoveryComplete, new DiscoveryCompletePayload { TotalTests = discoveryCompleteEventArgs.TotalCount, - LastDiscoveredTests = discoveryCompleteEventArgs.IsAborted ? null : _pathConverter.UpdateTestCases(lastChunk, PathConversionDirection.Send), + // TODO: avoid failing when lastChunk is null + LastDiscoveredTests = discoveryCompleteEventArgs.IsAborted ? null : _pathConverter.UpdateTestCases(lastChunk!, PathConversionDirection.Send), IsAborted = discoveryCompleteEventArgs.IsAborted, Metrics = discoveryCompleteEventArgs.Metrics, FullyDiscoveredSources = discoveryCompleteEventArgs.FullyDiscoveredSources, @@ -250,10 +249,10 @@ public void DiscoveryComplete(DiscoveryCompleteEventArgs discoveryCompleteEventA } /// - public int LaunchProcessWithDebuggerAttached(TestProcessStartInfo testProcessStartInfo) + public int LaunchProcessWithDebuggerAttached(TestProcessStartInfo? testProcessStartInfo) { var waitHandle = new ManualResetEventSlim(false); - Message ackMessage = null; + Message? ackMessage = null; _onLaunchAdapterProcessWithDebuggerAttachedAckReceived = (ackRawMessage) => { ackMessage = ackRawMessage; @@ -282,7 +281,7 @@ public bool AttachDebuggerToProcess(AttachDebuggerInfo attachDebuggerInfo) return false; } - Message ackMessage = null; + Message? ackMessage = null; var waitHandle = new ManualResetEventSlim(false); _onAttachDebuggerAckRecieved = (ackRawMessage) => @@ -295,7 +294,7 @@ public bool AttachDebuggerToProcess(AttachDebuggerInfo attachDebuggerInfo) MessageType.AttachDebugger, new TestProcessAttachDebuggerPayload(attachDebuggerInfo.ProcessId) { - TargetFramework = attachDebuggerInfo.TargetFramework.ToString(), + TargetFramework = attachDebuggerInfo.TargetFramework?.ToString(), }, _protocolVersion); SendData(data); @@ -307,13 +306,12 @@ public bool AttachDebuggerToProcess(AttachDebuggerInfo attachDebuggerInfo) return _dataSerializer.DeserializePayload(ackMessage); } - public void OnMessageReceived(object sender, MessageReceivedEventArgs messageReceivedArgs) + public void OnMessageReceived(object? sender, MessageReceivedEventArgs messageReceivedArgs) { - var message = _dataSerializer.DeserializeMessage(messageReceivedArgs.Data); - + var message = _dataSerializer.DeserializeMessage(messageReceivedArgs.Data!); EqtTrace.Info("TestRequestHandler.OnMessageReceived: received message: {0}", message); - switch (message.MessageType) + switch (message?.MessageType) { case MessageType.VersionCheck: try @@ -344,14 +342,15 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec } // Send the negotiated protocol to request sender + TPDebug.Assert(_channel is not null, "_channel is null"); _channel.Send(_dataSerializer.SerializePayload(MessageType.VersionCheck, _protocolVersion)); // Can only do this after InitializeCommunication because TestHost cannot "Send Log" unless communications are initialized - if (!string.IsNullOrEmpty(EqtTrace.LogFile)) + if (!StringUtils.IsNullOrEmpty(EqtTrace.LogFile)) { SendLog(TestMessageLevel.Informational, string.Format(CrossPlatResources.TesthostDiagLogOutputFile, EqtTrace.LogFile)); } - else if (!string.IsNullOrEmpty(EqtTrace.ErrorOnInitialization)) + else if (!StringUtils.IsNullOrEmpty(EqtTrace.ErrorOnInitialization)) { SendLog(TestMessageLevel.Warning, EqtTrace.ErrorOnInitialization); } @@ -371,10 +370,13 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec { _testHostManagerFactoryReady.Wait(); var discoveryEventsHandler = new TestDiscoveryEventHandler(this); - var pathToAdditionalExtensions = _pathConverter.UpdatePaths(_dataSerializer.DeserializePayload>(message), PathConversionDirection.Receive); + var path = _dataSerializer.DeserializePayload>(message); + TPDebug.Assert(path is not null, "path is null"); + var pathToAdditionalExtensions = _pathConverter.UpdatePaths(path, PathConversionDirection.Receive); Action job = () => { EqtTrace.Info("TestRequestHandler.OnMessageReceived: Running job '{0}'.", message.MessageType); + TPDebug.Assert(_testHostManagerFactory is not null, "_testHostManagerFactory is null"); _testHostManagerFactory.GetDiscoveryManager().Initialize(pathToAdditionalExtensions, discoveryEventsHandler); }; _jobQueue.QueueJob(job, 0); @@ -395,11 +397,14 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec { _testHostManagerFactoryReady.Wait(); var discoveryEventsHandler = new TestDiscoveryEventHandler(this); - var discoveryCriteria = _pathConverter.UpdateDiscoveryCriteria(_dataSerializer.DeserializePayload(message), PathConversionDirection.Receive); + var discoveryCriteria = _dataSerializer.DeserializePayload(message); + TPDebug.Assert(discoveryCriteria is not null, "discoveryCriteria is null"); + discoveryCriteria = _pathConverter.UpdateDiscoveryCriteria(discoveryCriteria, PathConversionDirection.Receive); Action job = () => { EqtTrace.Info("TestRequestHandler.OnMessageReceived: Running job '{0}'.", message.MessageType); + TPDebug.Assert(_testHostManagerFactory is not null, "_testHostManagerFactory is null"); _testHostManagerFactory.GetDiscoveryManager() .DiscoverTests(discoveryCriteria, discoveryEventsHandler); }; @@ -422,10 +427,13 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec { _testHostManagerFactoryReady.Wait(); var testInitializeEventsHandler = new TestInitializeEventsHandler(this); - var pathToAdditionalExtensions = _pathConverter.UpdatePaths(_dataSerializer.DeserializePayload>(message), PathConversionDirection.Receive); + var pathToAdditionalExtensions = _dataSerializer.DeserializePayload>(message); + TPDebug.Assert(pathToAdditionalExtensions is not null, "pathToAdditionalExtensions is null"); + pathToAdditionalExtensions = _pathConverter.UpdatePaths(pathToAdditionalExtensions, PathConversionDirection.Receive); Action job = () => { EqtTrace.Info("TestRequestHandler.OnMessageReceived: Running job '{0}'.", message.MessageType); + TPDebug.Assert(_testHostManagerFactory is not null, "_testHostManagerFactory is null"); _testHostManagerFactory.GetExecutionManager().Initialize(pathToAdditionalExtensions, testInitializeEventsHandler); }; _jobQueue.QueueJob(job, 0); @@ -446,10 +454,13 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec { var testRunEventsHandler = new TestRunEventsHandler(this); _testHostManagerFactoryReady.Wait(); - var testRunCriteriaWithSources = _pathConverter.UpdateTestRunCriteriaWithSources(_dataSerializer.DeserializePayload(message), PathConversionDirection.Receive); + var testRunCriteriaWithSources = _dataSerializer.DeserializePayload(message); + TPDebug.Assert(testRunCriteriaWithSources is not null, "testRunCriteriaWithSources is null"); + testRunCriteriaWithSources = _pathConverter.UpdateTestRunCriteriaWithSources(testRunCriteriaWithSources, PathConversionDirection.Receive); Action job = () => { EqtTrace.Info("TestRequestHandler.OnMessageReceived: Running job '{0}'.", message.MessageType); + TPDebug.Assert(_testHostManagerFactory is not null, "_testHostManagerFactory is null"); _testHostManagerFactory.GetExecutionManager() .StartTestRun( testRunCriteriaWithSources.AdapterSourceMap, @@ -477,11 +488,14 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec { var testRunEventsHandler = new TestRunEventsHandler(this); _testHostManagerFactoryReady.Wait(); - var testRunCriteriaWithTests = _pathConverter.UpdateTestRunCriteriaWithTests(_dataSerializer.DeserializePayload(message), PathConversionDirection.Receive); + var testRunCriteriaWithTests = _dataSerializer.DeserializePayload(message); + TPDebug.Assert(testRunCriteriaWithTests is not null, "testRunCriteriaWithTests is null"); + testRunCriteriaWithTests = _pathConverter.UpdateTestRunCriteriaWithTests(testRunCriteriaWithTests, PathConversionDirection.Receive); Action job = () => { EqtTrace.Info("TestRequestHandler.OnMessageReceived: Running job '{0}'.", message.MessageType); + TPDebug.Assert(_testHostManagerFactory is not null, "_testHostManagerFactory is null"); _testHostManagerFactory.GetExecutionManager() .StartTestRun( testRunCriteriaWithTests.Tests, @@ -506,6 +520,7 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec case MessageType.CancelTestRun: _jobQueue.Pause(); _testHostManagerFactoryReady.Wait(); + TPDebug.Assert(_testHostManagerFactory is not null, "_testHostManagerFactory is null"); _testHostManagerFactory.GetExecutionManager().Cancel(new TestRunEventsHandler(this)); break; @@ -520,6 +535,7 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec case MessageType.CancelDiscovery: _jobQueue.Pause(); _testHostManagerFactoryReady.Wait(); + TPDebug.Assert(_testHostManagerFactory is not null, "_testHostManagerFactory is null"); _testHostManagerFactory.GetDiscoveryManager().Abort(new TestDiscoveryEventHandler(this)); break; @@ -528,6 +544,7 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec { _jobQueue.Pause(); _testHostManagerFactoryReady.Wait(); + TPDebug.Assert(_testHostManagerFactory is not null, "_testHostManagerFactory is null"); _testHostManagerFactory.GetExecutionManager().Abort(new TestRunEventsHandler(this)); } catch (Exception ex) @@ -561,12 +578,13 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec } } - private ITestCaseEventsHandler GetTestCaseEventsHandler(string runSettings) + private static ITestCaseEventsHandler? GetTestCaseEventsHandler(string? runSettings) { - ITestCaseEventsHandler testCaseEventsHandler = null; + ITestCaseEventsHandler? testCaseEventsHandler = null; // Listen to test case events only if data collection is enabled - if ((XmlRunSettingsUtilities.IsDataCollectionEnabled(runSettings) && DataCollectionTestCaseEventSender.Instance != null) || XmlRunSettingsUtilities.IsInProcDataCollectionEnabled(runSettings)) + if ((XmlRunSettingsUtilities.IsDataCollectionEnabled(runSettings) && DataCollectionTestCaseEventSender.Instance != null) + || XmlRunSettingsUtilities.IsInProcDataCollectionEnabled(runSettings)) { testCaseEventsHandler = new TestCaseEventsHandler(); } @@ -576,7 +594,7 @@ private ITestCaseEventsHandler GetTestCaseEventsHandler(string runSettings) private void SendData(string data) { - EqtTrace.Verbose("TestRequestHandler.SendData: sending data from testhost: {0}", data); - _channel.Send(data); + EqtTrace.Verbose("TestRequestHandler.SendData: sending data from testhost: {0}", data); + _channel?.Send(data); } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs index 0fca2bd65c..86aa86fbe7 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs @@ -33,8 +33,6 @@ using CrossPlatEngineResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; /// @@ -42,20 +40,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; /// internal abstract class BaseRunTests { - private readonly ITestEventsPublisher _testEventsPublisher; - private protected string _package; - private readonly IRequestData _requestData; - - /// - /// Specifies that the test run cancellation is requested - /// - private volatile bool _isCancellationRequested; - - /// - /// Active executor which is executing the tests currently - /// - private ITestExecutor _activeExecutor; - private readonly ITestCaseEventsHandler _testCaseEventsHandler; + private readonly ITestCaseEventsHandler? _testCaseEventsHandler; private readonly ITestPlatformEventSource _testPlatformEventSource; /// @@ -73,6 +58,19 @@ internal abstract class BaseRunTests /// private readonly IDataSerializer _dataSerializer; + private protected string? _package; + private readonly IRequestData _requestData; + + /// + /// Specifies that the test run cancellation is requested + /// + private volatile bool _isCancellationRequested; + + /// + /// Active executor which is executing the tests currently + /// + private ITestExecutor? _activeExecutor; + /// /// Initializes a new instance of the class. /// @@ -85,10 +83,10 @@ internal abstract class BaseRunTests /// Test platform event source. protected BaseRunTests( IRequestData requestData, - string package, - string runSettings, + string? package, + string? runSettings, TestExecutionContext testExecutionContext, - ITestCaseEventsHandler testCaseEventsHandler, + ITestCaseEventsHandler? testCaseEventsHandler, IInternalTestRunEventsHandler testRunEventsHandler, ITestPlatformEventSource testPlatformEventSource) : this( @@ -120,13 +118,13 @@ protected BaseRunTests( /// Data Serializer for cloning TestCase and test results object. protected BaseRunTests( IRequestData requestData, - string package, - string runSettings, + string? package, + string? runSettings, TestExecutionContext testExecutionContext, - ITestCaseEventsHandler testCaseEventsHandler, + ITestCaseEventsHandler? testCaseEventsHandler, IInternalTestRunEventsHandler testRunEventsHandler, ITestPlatformEventSource testPlatformEventSource, - ITestEventsPublisher testEventsPublisher, + ITestEventsPublisher? testEventsPublisher, IThread platformThread, IDataSerializer dataSerializer) { @@ -139,7 +137,6 @@ protected BaseRunTests( _isCancellationRequested = false; _testPlatformEventSource = testPlatformEventSource; - _testEventsPublisher = testEventsPublisher; _platformThread = platformThread; _dataSerializer = dataSerializer; @@ -170,7 +167,7 @@ protected BaseRunTests( /// /// Gets the run settings. /// - protected string RunSettings { get; } + protected string? RunSettings { get; } /// /// Gets the test execution context. @@ -199,9 +196,8 @@ public void RunTests() { using (TestRunCache) { - TimeSpan elapsedTime = TimeSpan.Zero; - - Exception exception = null; + TimeSpan? elapsedTime = null; + Exception? exception = null; bool isAborted = false; bool shutdownAfterRun = false; @@ -211,9 +207,16 @@ public void RunTests() SendSessionStart(); elapsedTime = RunTestsInternal(); - - // Check the adapter setting for shutting down this process after run - shutdownAfterRun = FrameworkHandle.EnableShutdownAfterTestRun; + if (elapsedTime is null) + { + EqtTrace.Error("BaseRunTests.RunTests: Failed to run the tests. Reason: GetExecutorUriExtensionMap returned null."); + isAborted = true; + } + else + { + // Check the adapter setting for shutting down this process after run + shutdownAfterRun = FrameworkHandle.EnableShutdownAfterTestRun; + } } catch (Exception ex) { @@ -230,7 +233,7 @@ public void RunTests() try { // Send the test run complete event. - RaiseTestRunComplete(exception, _isCancellationRequested, isAborted, elapsedTime); + RaiseTestRunComplete(exception, _isCancellationRequested, isAborted, elapsedTime ?? TimeSpan.Zero); } catch (Exception ex2) { @@ -274,7 +277,7 @@ internal void Cancel() protected abstract void BeforeRaisingTestRunComplete(bool exceptionsHitDuringRunTests); - protected abstract IEnumerable> GetExecutorUriExtensionMap( + protected abstract IEnumerable>? GetExecutorUriExtensionMap( IFrameworkHandle testExecutorFrameworkHandle, RunContext runContext); @@ -303,7 +306,7 @@ protected abstract bool ShouldAttachDebuggerToTestHost( protected abstract void SendSessionEnd(); - private void CancelTestRunInternal(ITestExecutor executor) + private static void CancelTestRunInternal(ITestExecutor executor) { try { @@ -314,23 +317,30 @@ private void CancelTestRunInternal(ITestExecutor executor) EqtTrace.Info("{0}.Cancel threw an exception: {1} ", executor.GetType().FullName, e); } } - private void OnTestRunMessage(object sender, TestRunMessageEventArgs e) + private void OnTestRunMessage(object? sender, TestRunMessageEventArgs e) { TestRunEventsHandler.HandleLogMessage(e.Level, e.Message); } - private TimeSpan RunTestsInternal() + private TimeSpan? RunTestsInternal() { long totalTests = 0; - var executorUriExtensionMap = GetExecutorUriExtensionMap(FrameworkHandle, RunContext); - // Set on the logger the TreatAdapterErrorAsWarning setting from runsettings. SetAdapterLoggingSettings(); + var executorUriExtensionMap = GetExecutorUriExtensionMap(FrameworkHandle, RunContext); + var stopwatch = new Stopwatch(); stopwatch.Start(); + _testPlatformEventSource.ExecutionStart(); + + if (executorUriExtensionMap is null) + { + return null; + } + var exceptionsHitDuringRunTests = RunTestInternalWithExecutors( executorUriExtensionMap, totalTests); @@ -344,11 +354,12 @@ private TimeSpan RunTestsInternal() private bool RunTestInternalWithExecutors(IEnumerable> executorUriExtensionMap, long totalTests) { // Collecting Total Number of Adapters Discovered in Machine. - _requestData.MetricsCollection.Add(TelemetryDataConstants.NumberOfAdapterDiscoveredDuringExecution, executorUriExtensionMap.Count()); + var executorUriExtensionMapList = executorUriExtensionMap as IList> ?? executorUriExtensionMap.ToList(); + _requestData.MetricsCollection.Add(TelemetryDataConstants.NumberOfAdapterDiscoveredDuringExecution, executorUriExtensionMapList.Count); var attachedToTestHost = false; var executorCache = new Dictionary>(); - foreach (var executorUriExtensionTuple in executorUriExtensionMap) + foreach (var executorUriExtensionTuple in executorUriExtensionMapList) { // Avoid processing the same executor twice. if (executorCache.ContainsKey(executorUriExtensionTuple.Item1.AbsoluteUri)) @@ -360,7 +371,7 @@ private bool RunTestInternalWithExecutors(IEnumerable> execut var extensionManager = GetExecutorExtensionManager(executorUriExtensionTuple.Item2); // Look up the executor. - var executor = extensionManager.TryGetTestExtension(executorUriExtensionTuple.Item1); + var executor = extensionManager?.TryGetTestExtension(executorUriExtensionTuple.Item1); if (executor == null) { // Commenting this out because of a compatibility issue with Microsoft.Dotnet.ProjectModel released on nuGet.org. @@ -418,7 +429,7 @@ private bool RunTestInternalWithExecutors(IEnumerable> execut var executorsFromDeprecatedLocations = false; double totalTimeTakenByAdapters = 0; - foreach (var executorUriExtensionTuple in executorUriExtensionMap) + foreach (var executorUriExtensionTuple in executorUriExtensionMapList) { var executorUri = executorUriExtensionTuple.Item1.AbsoluteUri; // Get the executor from the cache. @@ -481,7 +492,7 @@ private bool RunTestInternalWithExecutors(IEnumerable> execut { var executorLocation = executor.Value.GetType().GetTypeInfo().Assembly.GetAssemblyLocation(); - executorsFromDeprecatedLocations |= Path.GetDirectoryName(executorLocation).Equals(CrossPlatEngine.Constants.DefaultAdapterLocation); + executorsFromDeprecatedLocations |= Path.GetDirectoryName(executorLocation)!.Equals(CrossPlatEngine.Constants.DefaultAdapterLocation); } totalTests = TestRunCache.TotalExecutedTests; @@ -538,11 +549,11 @@ private bool NotRequiredStaThread() return _runConfiguration.ExecutionThreadApartmentState != PlatformApartmentState.STA; } - private TestExecutorExtensionManager GetExecutorExtensionManager(string extensionAssembly) + private static TestExecutorExtensionManager? GetExecutorExtensionManager(string extensionAssembly) { try { - if (string.IsNullOrEmpty(extensionAssembly) + if (StringUtils.IsNullOrEmpty(extensionAssembly) || string.Equals(extensionAssembly, ObjectModel.Constants.UnspecifiedAdapterPath)) { // full execution. Since the extension manager is cached this can be created multiple times without harming performance. @@ -577,7 +588,7 @@ private void SetAdapterLoggingSettings() } private void RaiseTestRunComplete( - Exception exception, + Exception? exception, bool canceled, bool aborted, TimeSpan elapsedTime) @@ -604,7 +615,7 @@ private void RaiseTestRunComplete( var testRunChangedEventArgs = new TestRunChangedEventArgs(runStats, lastChunkTestResults, Enumerable.Empty()); // Adding Metrics along with Test Run Complete Event Args - Collection attachments = FrameworkHandle?.Attachments; + Collection? attachments = FrameworkHandle?.Attachments; var testRunCompleteEventArgs = new TestRunCompleteEventArgs( runStats, canceled, @@ -632,10 +643,10 @@ private void RaiseTestRunComplete( private bool IsTestSourceIsPackage() { - return !string.IsNullOrEmpty(_package); + return !StringUtils.IsNullOrEmpty(_package); } - private void OnCacheHit(TestRunStatistics testRunStats, ICollection results, ICollection inProgressTestCases) + private void OnCacheHit(TestRunStatistics testRunStats, ICollection results, ICollection? inProgressTestCases) { if (TestRunEventsHandler != null) { @@ -675,9 +686,9 @@ private bool TryToRunInStaThread(Action action, bool waitForCompletion) private void UpdateTestCaseSourceToPackage( ICollection testResults, - ICollection inProgressTestCases, + ICollection? inProgressTestCases, out ICollection updatedTestResults, - out ICollection updatedInProgressTestCases) + out ICollection? updatedInProgressTestCases) { EqtTrace.Verbose("BaseRunTests.UpdateTestCaseSourceToPackage: Update source details for testResults and testCases."); @@ -685,13 +696,14 @@ private void UpdateTestCaseSourceToPackage( updatedInProgressTestCases = UpdateInProgressTests(inProgressTestCases, _package); } - private ICollection UpdateTestResults(ICollection testResults, string package) + private ICollection UpdateTestResults(ICollection testResults, string? package) { ICollection updatedTestResults = new List(); foreach (var testResult in testResults) { var updatedTestResult = _dataSerializer.Clone(testResult); + TPDebug.Assert(updatedTestResult is not null, "updatedTestResult is null"); updatedTestResult.TestCase.Source = package; updatedTestResults.Add(updatedTestResult); } @@ -699,7 +711,7 @@ private ICollection UpdateTestResults(ICollection testRe return updatedTestResults; } - private ICollection UpdateInProgressTests(ICollection inProgressTestCases, string package) + private ICollection? UpdateInProgressTests(ICollection? inProgressTestCases, string? package) { if (inProgressTestCases == null) { @@ -710,6 +722,7 @@ private ICollection UpdateInProgressTests(ICollection inProg foreach (var inProgressTestCase in inProgressTestCases) { var updatedTestCase = _dataSerializer.Clone(inProgressTestCase); + TPDebug.Assert(updatedTestCase is not null, "updatedTestCase is null"); updatedTestCase.Source = package; updatedTestCases.Add(updatedTestCase); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs index f69c973d52..dfef658b2c 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs @@ -22,8 +22,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; /// @@ -32,10 +30,10 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; public class ExecutionManager : IExecutionManager { private readonly ITestPlatformEventSource _testPlatformEventSource; - private BaseRunTests _activeTestRun; private readonly IRequestData _requestData; - private readonly TestSessionMessageLogger _sessionMessageLogger; - private ITestMessageEventHandler _testMessageEventsHandler; + private readonly TestSessionMessageLogger? _sessionMessageLogger; + private BaseRunTests? _activeTestRun; + private ITestMessageEventHandler? _testMessageEventsHandler; /// /// Initializes a new instance of the class. @@ -63,7 +61,7 @@ protected ExecutionManager(ITestPlatformEventSource testPlatformEventSource, IRe /// Initializes the execution manager. /// /// The path to additional extensions. - public void Initialize(IEnumerable pathToAdditionalExtensions, ITestMessageEventHandler testMessageEventsHandler) + public void Initialize(IEnumerable? pathToAdditionalExtensions, ITestMessageEventHandler testMessageEventsHandler) { // Clear the request data metrics left over from a potential previous run. _requestData.MetricsCollection?.Metrics?.Clear(); @@ -80,7 +78,10 @@ public void Initialize(IEnumerable pathToAdditionalExtensions, ITestMess LoadExtensions(); //unsubscribe session logger - _sessionMessageLogger.TestRunMessage -= TestSessionMessageHandler; + if (_sessionMessageLogger is not null) + { + _sessionMessageLogger.TestRunMessage -= TestSessionMessageHandler; + } _testPlatformEventSource.AdapterSearchStop(); } @@ -96,18 +97,17 @@ public void Initialize(IEnumerable pathToAdditionalExtensions, ITestMess /// EventHandler for handling execution events from Engine. public void StartTestRun( Dictionary> adapterSourceMap, - string package, - string runSettings, + string? package, + string? runSettings, TestExecutionContext testExecutionContext, - ITestCaseEventsHandler testCaseEventsHandler, + ITestCaseEventsHandler? testCaseEventsHandler, IInternalTestRunEventsHandler runEventsHandler) { try { - InitializeDataCollectors(runSettings, testCaseEventsHandler as ITestEventsPublisher, TestSourcesUtility.GetDefaultCodebasePath(adapterSourceMap)); + InitializeDataCollectors(runSettings, testCaseEventsHandler as ITestEventsPublisher, TestSourcesUtility.GetDefaultCodebasePath(adapterSourceMap!)); _activeTestRun = new RunTestsWithSources(_requestData, adapterSourceMap, package, runSettings, testExecutionContext, testCaseEventsHandler, runEventsHandler); - _activeTestRun.RunTests(); } catch (Exception e) @@ -132,10 +132,10 @@ public void StartTestRun( /// EventHandler for handling execution events from Engine. public void StartTestRun( IEnumerable tests, - string package, - string runSettings, + string? package, + string? runSettings, TestExecutionContext testExecutionContext, - ITestCaseEventsHandler testCaseEventsHandler, + ITestCaseEventsHandler? testCaseEventsHandler, IInternalTestRunEventsHandler runEventsHandler) { try @@ -143,7 +143,6 @@ public void StartTestRun( InitializeDataCollectors(runSettings, testCaseEventsHandler as ITestEventsPublisher, TestSourcesUtility.GetDefaultCodebasePath(tests)); _activeTestRun = new RunTestsWithTests(_requestData, tests, package, runSettings, testExecutionContext, testCaseEventsHandler, runEventsHandler); - _activeTestRun.RunTests(); } catch (Exception e) @@ -190,7 +189,7 @@ public void Abort(IInternalTestRunEventsHandler testRunEventsHandler) } #endregion - private void LoadExtensions() + private static void LoadExtensions() { try { @@ -215,22 +214,24 @@ private void LoadExtensions() /// /// Initializes out-proc and in-proc data collectors. /// - private void InitializeDataCollectors(string runSettings, ITestEventsPublisher testEventsPublisher, string defaultCodeBase) + private static void InitializeDataCollectors(string? runSettings, ITestEventsPublisher? testEventsPublisher, string? defaultCodeBase) { // Initialize out-proc data collectors if declared in run settings. if (DataCollectionTestCaseEventSender.Instance != null && XmlRunSettingsUtilities.IsDataCollectionEnabled(runSettings)) { + TPDebug.Assert(testEventsPublisher is not null, "testEventsPublisher is null"); _ = new ProxyOutOfProcDataCollectionManager(DataCollectionTestCaseEventSender.Instance, testEventsPublisher); } // Initialize in-proc data collectors if declared in run settings. if (XmlRunSettingsUtilities.IsInProcDataCollectionEnabled(runSettings)) { + TPDebug.Assert(testEventsPublisher is not null, "testEventsPublisher is null"); _ = new InProcDataCollectionExtensionManager(runSettings, testEventsPublisher, defaultCodeBase, TestPluginCache.Instance); } } - private void TestSessionMessageHandler(object sender, TestRunMessageEventArgs e) + private void TestSessionMessageHandler(object? sender, TestRunMessageEventArgs e) { if (_testMessageEventsHandler != null) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/MSTestV1TelemetryHelper.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/MSTestV1TelemetryHelper.cs index 9550482fd6..2d268b9a4b 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/MSTestV1TelemetryHelper.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/MSTestV1TelemetryHelper.cs @@ -3,24 +3,23 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Microsoft.VisualStudio.TestPlatform.ObjectModel; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; internal class MsTestV1TelemetryHelper { - private static TestProperty s_testTypeProperty; - private static TestProperty s_extensionIdProperty; + private static TestProperty? s_testTypeProperty; + private static TestProperty? s_extensionIdProperty; - internal static bool IsMsTestV1Adapter(Uri executorUri) + internal static bool IsMsTestV1Adapter([NotNullWhen(true)] Uri? executorUri) { - return IsMsTestV1Adapter(executorUri.AbsoluteUri); + return IsMsTestV1Adapter(executorUri?.AbsoluteUri); } - internal static bool IsMsTestV1Adapter(string executorUri) + internal static bool IsMsTestV1Adapter([NotNullWhen(true)] string? executorUri) { return string.Equals(executorUri, "executor://mstestadapter/v1", StringComparison.OrdinalIgnoreCase); } @@ -50,16 +49,16 @@ internal static void AddTelemetry(TestResult testResult, IDictionary(s_extensionIdProperty, null); - var hasExtension = !string.IsNullOrWhiteSpace(testExtension); + var testExtension = testResult.GetPropertyValue(s_extensionIdProperty, null); + var hasExtension = !testExtension.IsNullOrWhiteSpace(); - if (hasExtension && testExtension.StartsWith("urn:")) + if (hasExtension && testExtension!.StartsWith("urn:")) { // remove urn: prefix testExtension = testExtension.Remove(0, 4); diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithSources.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithSources.cs index cd3f624304..654976ead2 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithSources.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithSources.cs @@ -22,19 +22,17 @@ using CrossPlatEngineResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; internal class RunTestsWithSources : BaseRunTests { private readonly Dictionary> _adapterSourceMap; - private Dictionary, IEnumerable> _executorUriVsSourceList; + private Dictionary, IEnumerable>? _executorUriVsSourceList; - private readonly ITestCaseEventsHandler _testCaseEventsHandler; + private readonly ITestCaseEventsHandler? _testCaseEventsHandler; - public RunTestsWithSources(IRequestData requestData, Dictionary> adapterSourceMap, string package, string runSettings, TestExecutionContext testExecutionContext, ITestCaseEventsHandler testCaseEventsHandler, IInternalTestRunEventsHandler testRunEventsHandler) + public RunTestsWithSources(IRequestData requestData, Dictionary> adapterSourceMap, string? package, string? runSettings, TestExecutionContext testExecutionContext, ITestCaseEventsHandler? testCaseEventsHandler, IInternalTestRunEventsHandler testRunEventsHandler) : this(requestData, adapterSourceMap, package, runSettings, testExecutionContext, testCaseEventsHandler, testRunEventsHandler, null) { } @@ -51,7 +49,7 @@ public RunTestsWithSources(IRequestData requestData, Dictionary /// /// - internal RunTestsWithSources(IRequestData requestData, Dictionary> adapterSourceMap, string package, string runSettings, TestExecutionContext testExecutionContext, ITestCaseEventsHandler testCaseEventsHandler, IInternalTestRunEventsHandler testRunEventsHandler, Dictionary, IEnumerable> executorUriVsSourceList) + internal RunTestsWithSources(IRequestData requestData, Dictionary> adapterSourceMap, string? package, string? runSettings, TestExecutionContext testExecutionContext, ITestCaseEventsHandler? testCaseEventsHandler, IInternalTestRunEventsHandler testRunEventsHandler, Dictionary, IEnumerable>? executorUriVsSourceList) : base(requestData, package, runSettings, testExecutionContext, testCaseEventsHandler, testRunEventsHandler, TestPlatformEventSource.Instance) { _adapterSourceMap = adapterSourceMap; @@ -75,7 +73,7 @@ private void LogWarningOnNoTestsExecuted() { IEnumerable sources = new List(); var sourcesArray = _adapterSourceMap.Values - .Aggregate(sources, (current, enumerable) => current.Concat(enumerable)).ToArray(); + .Aggregate(sources, (current, enumerable) => enumerable is not null ? current.Concat(enumerable) : current).ToArray(); var sourcesString = string.Join(" ", sourcesArray); if (TestExecutionContext.TestCaseFilter != null) @@ -101,7 +99,7 @@ protected override IEnumerable> GetExecutorUriExtensionMap(IF _executorUriVsSourceList = GetExecutorVsSourcesList(testExecutorFrameworkHandle); var executorUris = _executorUriVsSourceList.Keys; - runContext.FilterExpressionWrapper = !string.IsNullOrEmpty(TestExecutionContext.TestCaseFilter) + runContext.FilterExpressionWrapper = !TestExecutionContext.TestCaseFilter.IsNullOrEmpty() ? new FilterExpressionWrapper(TestExecutionContext.TestCaseFilter, TestExecutionContext.FilterOptions) : null; @@ -111,10 +109,10 @@ protected override IEnumerable> GetExecutorUriExtensionMap(IF protected override void InvokeExecutor( LazyExtension executor, Tuple executorUriExtensionTuple, - RunContext runContext, - IFrameworkHandle frameworkHandle) + RunContext? runContext, + IFrameworkHandle? frameworkHandle) { - executor?.Value.RunTests(_executorUriVsSourceList[executorUriExtensionTuple], runContext, frameworkHandle); + executor?.Value.RunTests(_executorUriVsSourceList?[executorUriExtensionTuple], runContext, frameworkHandle); } /// @@ -127,7 +125,7 @@ protected override bool ShouldAttachDebuggerToTestHost( // the default test host by default to preserve old behavior. return executor?.Value is not ITestExecutor2 convertedExecutor || convertedExecutor.ShouldAttachToTestHost( - _executorUriVsSourceList[executorUriExtensionTuple], + _executorUriVsSourceList?[executorUriExtensionTuple], runContext); } @@ -140,7 +138,7 @@ private Dictionary, IEnumerable> GetExecutorVsSources var verifiedExtensionSourceMap = new Dictionary>(); - // Validate the sources + // Validate the sources foreach (var kvp in _adapterSourceMap) { var verifiedSources = DiscoveryManager.GetValidSources(kvp.Value, logger, _package); @@ -158,12 +156,11 @@ private Dictionary, IEnumerable> GetExecutorVsSources foreach (var kvp in verifiedExtensionSourceMap) { - Dictionary, IEnumerable> - discovererToSourcesMap = DiscovererEnumerator.GetDiscovererToSourcesMap( - kvp.Key, - kvp.Value, - logger, - new AssemblyProperties()); + var discovererToSourcesMap = DiscovererEnumerator.GetDiscovererToSourcesMap( + kvp.Key, + kvp.Value, + logger, + new AssemblyProperties()); // Warning is logged by the inner layer if (discovererToSourcesMap == null || discovererToSourcesMap.Count == 0) @@ -205,15 +202,6 @@ private Dictionary, IEnumerable> GetExecutorVsSources return result; } - private static string TestCaseFilterToShow(string testCaseFilter) - { - var maxTestCaseFilterToShowLength = 63; - string testCaseFilterToShow = testCaseFilter.Length > maxTestCaseFilterToShowLength - ? testCaseFilter.Substring(0, maxTestCaseFilterToShowLength - 3) + "..." - : testCaseFilter; - return testCaseFilterToShow; - } - /// /// Sends Session-End event on in-proc datacollectors /// @@ -233,9 +221,9 @@ protected override void SendSessionStart() return; } - var properties = new Dictionary + var properties = new Dictionary { - { "TestSources", TestSourcesUtility.GetSources(_adapterSourceMap) } + { "TestSources", TestSourcesUtility.GetSources(_adapterSourceMap!) } }; _testCaseEventsHandler.SendSessionStart(properties); diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithTests.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithTests.cs index 16825c8cab..bab406d8eb 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithTests.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/RunTestsWithTests.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; @@ -16,19 +15,16 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; internal class RunTestsWithTests : BaseRunTests { private readonly IEnumerable _testCases; + private readonly ITestCaseEventsHandler? _testCaseEventsHandler; - private Dictionary, List> _executorUriVsTestList; - - private readonly ITestCaseEventsHandler _testCaseEventsHandler; + private Dictionary, List>? _executorUriVsTestList; - public RunTestsWithTests(IRequestData requestData, IEnumerable testCases, string package, string runSettings, TestExecutionContext testExecutionContext, ITestCaseEventsHandler testCaseEventsHandler, IInternalTestRunEventsHandler testRunEventsHandler) + public RunTestsWithTests(IRequestData requestData, IEnumerable testCases, string? package, string? runSettings, TestExecutionContext testExecutionContext, ITestCaseEventsHandler? testCaseEventsHandler, IInternalTestRunEventsHandler testRunEventsHandler) : this(requestData, testCases, package, runSettings, testExecutionContext, testCaseEventsHandler, testRunEventsHandler, null) { } @@ -44,7 +40,7 @@ public RunTestsWithTests(IRequestData requestData, IEnumerable testCas /// /// /// - internal RunTestsWithTests(IRequestData requestData, IEnumerable testCases, string package, string runSettings, TestExecutionContext testExecutionContext, ITestCaseEventsHandler testCaseEventsHandler, IInternalTestRunEventsHandler testRunEventsHandler, Dictionary, List> executorUriVsTestList) + internal RunTestsWithTests(IRequestData requestData, IEnumerable testCases, string? package, string? runSettings, TestExecutionContext testExecutionContext, ITestCaseEventsHandler? testCaseEventsHandler, IInternalTestRunEventsHandler testRunEventsHandler, Dictionary, List>? executorUriVsTestList) : base(requestData, package, runSettings, testExecutionContext, testCaseEventsHandler, testRunEventsHandler, TestPlatformEventSource.Instance) { _testCases = testCases; @@ -61,7 +57,7 @@ protected override IEnumerable> GetExecutorUriExtensionMap(IF { _executorUriVsTestList = GetExecutorVsTestCaseList(_testCases); - Debug.Assert(TestExecutionContext.TestCaseFilter == null, "TestCaseFilter should be null for specific tests."); + TPDebug.Assert(TestExecutionContext.TestCaseFilter == null, "TestCaseFilter should be null for specific tests."); runContext.FilterExpressionWrapper = null; return _executorUriVsTestList.Keys; @@ -70,10 +66,10 @@ protected override IEnumerable> GetExecutorUriExtensionMap(IF protected override void InvokeExecutor( LazyExtension executor, Tuple executorUri, - RunContext runContext, - IFrameworkHandle frameworkHandle) + RunContext? runContext, + IFrameworkHandle? frameworkHandle) { - executor?.Value.RunTests(_executorUriVsTestList[executorUri], runContext, frameworkHandle); + executor?.Value.RunTests(_executorUriVsTestList?[executorUri], runContext, frameworkHandle); } /// @@ -85,7 +81,7 @@ protected override bool ShouldAttachDebuggerToTestHost( // If the adapter doesn't implement the new test executor interface we should attach to // the default test host by default to preserve old behavior. return executor?.Value is not ITestExecutor2 convertedExecutor - || convertedExecutor.ShouldAttachToTestHost(_executorUriVsTestList[executorUri], runContext); + || convertedExecutor.ShouldAttachToTestHost(_executorUriVsTestList?[executorUri], runContext); } /// @@ -107,7 +103,7 @@ protected override void SendSessionStart() return; } - var properties = new Dictionary + var properties = new Dictionary { { "TestSources", TestSourcesUtility.GetSources(_testCases) } }; @@ -118,7 +114,7 @@ protected override void SendSessionStart() /// /// Returns the executor Vs TestCase list /// - private Dictionary, List> GetExecutorVsTestCaseList(IEnumerable tests) + private static Dictionary, List> GetExecutorVsTestCaseList(IEnumerable tests) { var result = new Dictionary, List>(); foreach (var test in tests) @@ -129,16 +125,13 @@ private Dictionary, List> GetExecutorVsTestCaseList test.ExecutorUri, ObjectModel.Constants.UnspecifiedAdapterPath); - if (result.TryGetValue(executorUriExtensionTuple, out List testList)) + if (result.TryGetValue(executorUriExtensionTuple, out List? testList)) { testList.Add(test); } else { - testList = new List - { - test - }; + testList = new List { test }; result.Add(executorUriExtensionTuple, testList); } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/TestRunCache.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/TestRunCache.cs index f75a6edafa..dc2201a2bf 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/TestRunCache.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/TestRunCache.cs @@ -4,16 +4,12 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Diagnostics; using System.Linq; using System.Threading; using Microsoft.VisualStudio.TestPlatform.ObjectModel; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; /// @@ -54,7 +50,7 @@ internal class TestRunCache : ITestRunCache /// /// Timer for cache /// - private Timer _timer; + private readonly Timer _timer; /// /// Last time results were sent. @@ -84,9 +80,9 @@ internal class TestRunCache : ITestRunCache /// The on cache hit. internal TestRunCache(long cacheSize, TimeSpan cacheTimeout, OnCacheHit onCacheHit) { - Debug.Assert(cacheSize > 0, "Buffer size cannot be less than zero"); - Debug.Assert(onCacheHit != null, "Callback which listens for cache size limit cannot be null."); - Debug.Assert(cacheTimeout > TimeSpan.MinValue, "The cache timeout must be greater than min value."); + TPDebug.Assert(cacheSize > 0, "Buffer size cannot be less than zero"); + TPDebug.Assert(onCacheHit != null, "Callback which listens for cache size limit cannot be null."); + TPDebug.Assert(cacheTimeout > TimeSpan.MinValue, "The cache timeout must be greater than min value."); if (cacheTimeout.TotalMilliseconds > int.MaxValue) { @@ -233,7 +229,7 @@ public void OnNewTestResult(TestResult testResult) /// The completed Test. /// /// True if this test has been removed from the list of in progress tests. - public bool OnTestCompletion(TestCase completedTest) + public bool OnTestCompletion(TestCase? completedTest) { lock (_syncObject) { @@ -299,7 +295,6 @@ protected virtual void Dispose(bool disposing) if (_timer != null) { _timer.Dispose(); - _timer = null; } // Indicate that the instance has been disposed. @@ -352,7 +347,7 @@ private void SendResults() EqtTrace.Verbose("TestRunCache: OnNewTestResult: Notified the onCacheHit callback."); } - private void OnCacheTimeHit(object state) + private void OnCacheTimeHit(object? state) { lock (_syncObject) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Interfaces/ITestRunCache.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Interfaces/ITestRunCache.cs index 0a62623995..516fb348ec 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Interfaces/ITestRunCache.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Interfaces/ITestRunCache.cs @@ -7,8 +7,6 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; /// diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Microsoft.TestPlatform.CrossPlatEngine.csproj b/src/Microsoft.TestPlatform.CrossPlatEngine/Microsoft.TestPlatform.CrossPlatEngine.csproj index ae8da5bfae..f3315934ec 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Microsoft.TestPlatform.CrossPlatEngine.csproj +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Microsoft.TestPlatform.CrossPlatEngine.csproj @@ -6,7 +6,7 @@ Microsoft.TestPlatform.CrossPlatEngine - netstandard2.0;netstandard1.3;net451 + net6.0;netstandard2.0;netstandard1.3;net451 net6.0 false diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/NullableHelpers.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/NullableHelpers.cs index c727e101c0..d8d6e09e8b 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/NullableHelpers.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/NullableHelpers.cs @@ -16,12 +16,12 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; internal static class StringUtils { - /// + /// [SuppressMessage("ApiDesign", "RS0030:Do not used banned APIs", Justification = "Replacement API to allow nullable hints for compiler")] public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)] this string? value) => string.IsNullOrEmpty(value); - /// + /// [SuppressMessage("ApiDesign", "RS0030:Do not used banned APIs", Justification = "Replacement API to allow nullable hints for compiler")] public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)] this string? value) => string.IsNullOrWhiteSpace(value); diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/NullableHelpers.tt b/src/Microsoft.TestPlatform.CrossPlatEngine/NullableHelpers.tt index 7e3d8e7270..5564c17b1e 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/NullableHelpers.tt +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/NullableHelpers.tt @@ -19,15 +19,15 @@ namespace <#= System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("Name internal static class StringUtils { - /// + /// [SuppressMessage("ApiDesign", "RS0030:Do not used banned APIs", Justification = "Replacement API to allow nullable hints for compiler")] public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)] this string? value) => string.IsNullOrEmpty(value); - /// + /// [SuppressMessage("ApiDesign", "RS0030:Do not used banned APIs", Justification = "Replacement API to allow nullable hints for compiler")] public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)] this string? value) - => string.IsNullOrWhiteSpace(value); + => StringUtils.IsNullOrWhiteSpace(value); } [SuppressMessage("ApiDesign", "RS0030:Do not used banned APIs", Justification = "Replacement API to allow nullable hints for compiler")] diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/PostProcessing/ArtifactProcessingManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/PostProcessing/ArtifactProcessingManager.cs index 24c0474dc0..93a201f16c 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/PostProcessing/ArtifactProcessingManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/PostProcessing/ArtifactProcessingManager.cs @@ -89,19 +89,21 @@ public void CollectArtifacts(TestRunCompleteEventArgs testRunCompleteEventArgs, try { // We need to save in case of attachements, we'll show these at the end on console. - if (testRunCompleteEventArgs?.AttachmentSets.Count > 0) + if ((testRunCompleteEventArgs?.AttachmentSets.Count) <= 0) { - EqtTrace.Verbose($"ArtifactProcessingManager.CollectArtifacts: Saving data collectors artifacts for post process into {_processArtifactFolder}"); - Stopwatch watch = Stopwatch.StartNew(); - TPDebug.Assert(_testSessionProcessArtifactFolder is not null, "_testSessionProcessArtifactFolder is null"); - _fileHelper.CreateDirectory(_testSessionProcessArtifactFolder); - EqtTrace.Verbose($"ArtifactProcessingManager.CollectArtifacts: Persist runsettings \n{runSettingsXml}"); - _fileHelper.WriteAllTextToFile(Path.Combine(_testSessionProcessArtifactFolder, RunsettingsFileName), runSettingsXml); - var serializedExecutionComplete = _dataSerialized.SerializePayload(MessageType.ExecutionComplete, testRunCompleteEventArgs); - EqtTrace.Verbose($"ArtifactProcessingManager.CollectArtifacts: Persist ExecutionComplete message \n{serializedExecutionComplete}"); - _fileHelper.WriteAllTextToFile(Path.Combine(_testSessionProcessArtifactFolder, ExecutionCompleteFileName), serializedExecutionComplete); - EqtTrace.Verbose($"ArtifactProcessingManager.CollectArtifacts: Artifacts saved in {watch.Elapsed}"); + return; } + + EqtTrace.Verbose($"ArtifactProcessingManager.CollectArtifacts: Saving data collectors artifacts for post process into {_processArtifactFolder}"); + Stopwatch watch = Stopwatch.StartNew(); + TPDebug.Assert(_testSessionProcessArtifactFolder is not null, "_testSessionProcessArtifactFolder is null"); + _fileHelper.CreateDirectory(_testSessionProcessArtifactFolder); + EqtTrace.Verbose($"ArtifactProcessingManager.CollectArtifacts: Persist runsettings \n{runSettingsXml}"); + _fileHelper.WriteAllTextToFile(Path.Combine(_testSessionProcessArtifactFolder, RunsettingsFileName), runSettingsXml); + var serializedExecutionComplete = _dataSerialized.SerializePayload(MessageType.ExecutionComplete, testRunCompleteEventArgs); + EqtTrace.Verbose($"ArtifactProcessingManager.CollectArtifacts: Persist ExecutionComplete message \n{serializedExecutionComplete}"); + _fileHelper.WriteAllTextToFile(Path.Combine(_testSessionProcessArtifactFolder, ExecutionCompleteFileName), serializedExecutionComplete); + EqtTrace.Verbose($"ArtifactProcessingManager.CollectArtifacts: Artifacts saved in {watch.Elapsed}"); } catch (Exception e) { @@ -214,14 +216,13 @@ await _testRunAttachmentsProcessingManager.ProcessTestRunAttachmentsAsync(runset CancellationToken.None); } - private TestArtifacts[] LoadTestArtifacts() { TPDebug.Assert(_processArtifactFolder is not null, "_processArtifactFolder is null"); return _fileHelper.GetFiles(_processArtifactFolder, "*.*", SearchOption.AllDirectories) .Select(file => new { TestSessionId = Path.GetFileName(Path.GetDirectoryName(file)), Artifact = file }) .GroupBy(grp => grp.TestSessionId) - .Select(testSessionArtifact => new TestArtifacts(testSessionArtifact.Key, testSessionArtifact.Select(x => ParseArtifact(x.Artifact)).Where(x => x is not null).ToArray()!)) // Bang because null dataflow doesn't yet backport learning from the `Where` clause + .Select(testSessionArtifact => new TestArtifacts(testSessionArtifact.Key!, testSessionArtifact.Select(x => ParseArtifact(x.Artifact)).Where(x => x is not null).ToArray()!)) // Bang because null dataflow doesn't yet backport learning from the `Where` clause .ToArray(); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/PublicAPI/net6.0/PublicAPI.Shipped.txt b/src/Microsoft.TestPlatform.CrossPlatEngine/PublicAPI/net6.0/PublicAPI.Shipped.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/PublicAPI/net6.0/PublicAPI.Unshipped.txt b/src/Microsoft.TestPlatform.CrossPlatEngine/PublicAPI/net6.0/PublicAPI.Unshipped.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs index ef5dc13cf1..74ae4a04c9 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs @@ -25,8 +25,6 @@ using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; using Microsoft.VisualStudio.TestPlatform.Utilities; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; /// @@ -38,7 +36,7 @@ public class TestEngine : ITestEngine private readonly IProcessHelper _processHelper; private readonly IEnvironment _environment; - private ITestExtensionManager _testExtensionManager; + private ITestExtensionManager? _testExtensionManager; public TestEngine() : this(TestRuntimeProviderManager.Instance, new ProcessHelper()) @@ -87,7 +85,7 @@ public IProxyDiscoveryManager GetDiscoveryManager( requestData.MetricsCollection.Add(TelemetryDataConstants.TestSessionId, discoveryCriteria.TestSessionInfo?.Id.ToString() ?? string.Empty); // Get testhost managers by configuration, and either use it for in-process run. or for single source run. - List testHostManagers = GetTestRuntimeProvidersForUniqueConfigurations(discoveryCriteria.RunSettings, sourceToSourceDetailMap, warningLogger, out ITestRuntimeProvider testHostManager); + List testHostManagers = GetTestRuntimeProvidersForUniqueConfigurations(discoveryCriteria.RunSettings, sourceToSourceDetailMap, warningLogger, out ITestRuntimeProvider? testHostManager); // This is a big if that figures out if we can run in process. In process run is very restricted, it is non-parallel run // that has the same target framework as the current process, and it also must not be running in DesignMode (server mode / under IDE) @@ -105,6 +103,7 @@ public IProxyDiscoveryManager GetDiscoveryManager( } var testHostManagerInfo = testHostManagers[0]; + TPDebug.Assert(testHostManager is not null, "testHostManager is null"); // Don't intialize, we are taking an instance that we created already initialized in GetTestRuntimeProvidersForUniqueConfigurations // testHostManager.Initialize(TestSessionMessageLogger.Instance, testHostManagerInfo.RunSettings); @@ -126,6 +125,7 @@ public IProxyDiscoveryManager GetDiscoveryManager( hostManager?.Initialize(TestSessionMessageLogger.Instance, runtimeProviderInfo.RunSettings); ThrowExceptionIfTestHostManagerIsNull(hostManager, runtimeProviderInfo.RunSettings); + TPDebug.Assert(hostManager is not null, "hostManager is null"); // This function is used to either take a pre-existing proxy operation manager from // the test pool or to create a new proxy operation manager on the spot. @@ -134,6 +134,8 @@ public IProxyDiscoveryManager GetDiscoveryManager( string source, ProxyDiscoveryManager proxyDiscoveryManager) => { + TPDebug.Assert(discoveryCriteria.TestSessionInfo is not null, "discoveryCriteria.TestSessionInfo is null"); + // In case we have an active test session, we always prefer the already // created proxies instead of the ones that need to be created on the spot. var proxyOperationManager = TestSessionPool.Instance.TryTakeProxy( @@ -207,7 +209,7 @@ public IProxyExecutionManager GetExecutionManager( var isDataCollectorEnabled = XmlRunSettingsUtilities.IsDataCollectionEnabled(testRunCriteria.TestRunSettings); var isInProcDataCollectorEnabled = XmlRunSettingsUtilities.IsInProcDataCollectionEnabled(testRunCriteria.TestRunSettings); - var testHostProviders = GetTestRuntimeProvidersForUniqueConfigurations(testRunCriteria.TestRunSettings, sourceToSourceDetailMap, warningLogger, out ITestRuntimeProvider testHostManager); + var testHostProviders = GetTestRuntimeProvidersForUniqueConfigurations(testRunCriteria.TestRunSettings, sourceToSourceDetailMap, warningLogger, out ITestRuntimeProvider? testHostManager); if (ShouldRunInProcess( testRunCriteria.TestRunSettings, @@ -220,6 +222,7 @@ public IProxyExecutionManager GetExecutionManager( // // We know that we only have a single testHostManager here, because we figure that out in ShouldRunInProcess. ThrowExceptionIfTestHostManagerIsNull(testHostManager, testRunCriteria.TestRunSettings); + TPDebug.Assert(testHostManager is not null, "testHostManager is null"); // Don't intialize, we are taking an instance that we created already initialized in GetTestRuntimeProvidersForUniqueConfigurations // testHostManager.Initialize(TestSessionMessageLogger.Instance, testRunCriteria.TestRunSettings); @@ -227,7 +230,7 @@ public IProxyExecutionManager GetExecutionManager( // NOTE: The custom launcher should not be set when we have test session info available. if (testRunCriteria.TestHostLauncher != null) { - testHostManager.SetCustomLauncher(testRunCriteria.TestHostLauncher); + testHostManager!.SetCustomLauncher(testRunCriteria.TestHostLauncher); } return new InProcessProxyExecutionManager( @@ -263,7 +266,7 @@ internal IProxyExecutionManager CreateNonParallelExecutionManager(IRequestData r var sources = runtimeProviderInfo.SourceDetails.Select(r => r.Source).ToList(); var hostManager = _testHostProviderManager.GetTestHostManagerByRunConfiguration(runtimeProviderInfo.RunSettings, sources); ThrowExceptionIfTestHostManagerIsNull(hostManager, runtimeProviderInfo.RunSettings); - hostManager.Initialize(TestSessionMessageLogger.Instance, runtimeProviderInfo.RunSettings); + hostManager!.Initialize(TestSessionMessageLogger.Instance, runtimeProviderInfo.RunSettings); if (testRunCriteria.TestHostLauncher != null) { @@ -339,7 +342,7 @@ internal IProxyExecutionManager CreateNonParallelExecutionManager(IRequestData r } /// - public IProxyTestSessionManager GetTestSessionManager( + public IProxyTestSessionManager? GetTestSessionManager( IRequestData requestData, StartTestSessionCriteria testSessionCriteria, IDictionary sourceToSourceDetailMap, @@ -370,13 +373,13 @@ public IProxyTestSessionManager GetTestSessionManager( return null; } - Func proxyCreator = testRuntimeProviderInfo => + Func proxyCreator = testRuntimeProviderInfo => { var sources = testRuntimeProviderInfo.SourceDetails.Select(x => x.Source).ToList(); var hostManager = _testHostProviderManager.GetTestHostManagerByRunConfiguration(testRuntimeProviderInfo.RunSettings, sources); ThrowExceptionIfTestHostManagerIsNull(hostManager, testRuntimeProviderInfo.RunSettings); - hostManager.Initialize(TestSessionMessageLogger.Instance, testRuntimeProviderInfo.RunSettings); + hostManager!.Initialize(TestSessionMessageLogger.Instance, testRuntimeProviderInfo.RunSettings); if (testSessionCriteria.TestHostLauncher != null) { hostManager.SetCustomLauncher(testSessionCriteria.TestHostLauncher); @@ -429,7 +432,7 @@ private List GetTestRuntimeProvidersForUniqueConfigurat string runSettings, IDictionary sourceToSourceDetailMap, IWarningLogger warningLogger, - out ITestRuntimeProvider mostRecentlyCreatedInstance) + out ITestRuntimeProvider? mostRecentlyCreatedInstance) { // Group source details to get unique frameworks and architectures for which we will run, so we can figure // out which runtime providers would run them, and if the runtime provider is shared or not. @@ -531,7 +534,7 @@ private int VerifyParallelSettingAndCalculateParallelLevel( // In case of a background discovery we want to reduce the number of cores utilized // to leave enough power for other tasks. var runSettingsEnvVariables = InferRunSettingsHelper.GetEnvironmentVariables(runSettings); - string isBackgroundDiscoveryEnabled = null; + string? isBackgroundDiscoveryEnabled = null; if (runSettingsEnvVariables is not null && runSettingsEnvVariables.TryGetValue("VSTEST_BACKGROUND_DISCOVERY", out isBackgroundDiscoveryEnabled) && isBackgroundDiscoveryEnabled == "1" @@ -600,6 +603,7 @@ private bool ShouldRunInProcess( } var currentProcessPath = _processHelper.GetCurrentProcessFileName(); + TPDebug.Assert(currentProcessPath != null, "currentProcessPath is null"); // If running with the dotnet executable, then don't run in in process. if (currentProcessPath.EndsWith("dotnet", StringComparison.OrdinalIgnoreCase) @@ -629,7 +633,7 @@ private bool ShouldRunInProcess( return false; } - private static void ThrowExceptionIfTestHostManagerIsNull(ITestRuntimeProvider testHostManager, string settingsXml) + private static void ThrowExceptionIfTestHostManagerIsNull(ITestRuntimeProvider? testHostManager, string? settingsXml) { if (testHostManager == null) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/TestExtensionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/TestExtensionManager.cs index 029e4710e4..2f046c4f69 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/TestExtensionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/TestExtensionManager.cs @@ -4,11 +4,8 @@ using System.Collections.Generic; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; - using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; /// diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/TestHostManagerFactory.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/TestHostManagerFactory.cs index 81c660a6c2..e76633b9cb 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/TestHostManagerFactory.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/TestHostManagerFactory.cs @@ -7,8 +7,6 @@ using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; /// @@ -16,14 +14,14 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; /// public class TestHostManagerFactory : ITestHostManagerFactory { - private IDiscoveryManager _discoveryManager; - private IExecutionManager _executionManager; + private IDiscoveryManager? _discoveryManager; + private IExecutionManager? _executionManager; private readonly bool _telemetryOptedIn; /// /// Initializes a new instance of the class. /// - /// + /// /// /// A value indicating if the telemetry is opted in or not. /// @@ -46,7 +44,7 @@ public IDiscoveryManager GetDiscoveryManager() public IExecutionManager GetExecutionManager() => _executionManager ??= new ExecutionManager(GetRequestData(_telemetryOptedIn)); - private RequestData GetRequestData(bool telemetryOptedIn) + private static RequestData GetRequestData(bool telemetryOptedIn) { return new RequestData { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/TestSession/ProxyTestSessionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/TestSession/ProxyTestSessionManager.cs index afe5e29c4b..2625711d80 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/TestSession/ProxyTestSessionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/TestSession/ProxyTestSessionManager.cs @@ -18,8 +18,6 @@ using CrossPlatResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; /// @@ -40,23 +38,22 @@ private enum TestSessionState private volatile bool _proxySetupFailed; private readonly StartTestSessionCriteria _testSessionCriteria; private readonly int _maxTesthostCount; - private TestSessionInfo _testSessionInfo; - private readonly Func _proxyCreator; + private TestSessionInfo? _testSessionInfo; + private readonly Func _proxyCreator; private readonly List _runtimeProviders; private readonly IList _proxyContainerList; private readonly IDictionary _proxyMap; private readonly Stopwatch _testSessionStopwatch; private readonly Dictionary _sourceToRuntimeProviderInfoMap; - private IDictionary _testSessionEnvironmentVariables = new Dictionary(); + private Dictionary _testSessionEnvironmentVariables = new(); - private IDictionary TestSessionEnvironmentVariables + private IDictionary TestSessionEnvironmentVariables { get { if (_testSessionEnvironmentVariables.Count == 0) { - _testSessionEnvironmentVariables = InferRunSettingsHelper.GetEnvironmentVariables( - _testSessionCriteria.RunSettings) + _testSessionEnvironmentVariables = InferRunSettingsHelper.GetEnvironmentVariables(_testSessionCriteria.RunSettings) ?? _testSessionEnvironmentVariables; } @@ -74,7 +71,7 @@ private IDictionary TestSessionEnvironmentVariables public ProxyTestSessionManager( StartTestSessionCriteria criteria, int maxTesthostCount, - Func proxyCreator, + Func proxyCreator, List runtimeProviders) { _testSessionCriteria = criteria; @@ -231,9 +228,9 @@ public virtual bool StopSession(IRequestData requestData) /// The run settings. /// /// The dequeued proxy. - public virtual ProxyOperationManager DequeueProxy(string source, string runSettings) + public virtual ProxyOperationManager DequeueProxy(string source, string? runSettings) { - ProxyOperationManagerContainer proxyContainer = null; + ProxyOperationManagerContainer? proxyContainer = null; lock (_proxyOperationLockObject) { @@ -404,7 +401,7 @@ private void DisposeProxies() } } - private bool CheckRunSettingsAreCompatible(string requestRunSettings) + private bool CheckRunSettingsAreCompatible(string? requestRunSettings) { // Environment variable sets should be identical, otherwise it's not safe to reuse the // already running testhosts. diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/TestSession/TestSessionPool.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/TestSession/TestSessionPool.cs index 37511d73b0..c5383e0c80 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/TestSession/TestSessionPool.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/TestSession/TestSessionPool.cs @@ -3,14 +3,13 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; /// @@ -19,7 +18,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; public class TestSessionPool { private static readonly object InstanceLockObject = new(); - private static volatile TestSessionPool s_instance; + private static volatile TestSessionPool? s_instance; private readonly object _lockObject = new(); private readonly Dictionary _sessionPool; @@ -38,6 +37,7 @@ internal TestSessionPool() /// /// /// Thread-safe singleton pattern. + [AllowNull] public static TestSessionPool Instance { get @@ -99,7 +99,7 @@ public virtual bool KillSession(TestSessionInfo testSessionInfo, IRequestData re { // TODO (copoiena): What happens if some request is running for the current session ? // Should we stop the request as well ? Probably yes. - IProxyTestSessionManager proxyManager = null; + IProxyTestSessionManager? proxyManager = null; lock (_lockObject) { @@ -128,15 +128,15 @@ public virtual bool KillSession(TestSessionInfo testSessionInfo, IRequestData re /// The request data. /// /// The proxy object. - public virtual ProxyOperationManager TryTakeProxy( + public virtual ProxyOperationManager? TryTakeProxy( TestSessionInfo testSessionInfo, string source, - string runSettings, + string? runSettings, IRequestData requestData) { ValidateArg.NotNull(requestData, nameof(requestData)); - ProxyTestSessionManager sessionManager = null; + ProxyTestSessionManager? sessionManager = null; lock (_lockObject) { if (!_sessionPool.ContainsKey(testSessionInfo)) @@ -184,7 +184,7 @@ public virtual ProxyOperationManager TryTakeProxy( /// True if the operation succeeded, false otherwise. public virtual bool ReturnProxy(TestSessionInfo testSessionInfo, int proxyId) { - ProxyTestSessionManager sessionManager = null; + ProxyTestSessionManager? sessionManager = null; lock (_lockObject) { if (!_sessionPool.ContainsKey(testSessionInfo)) diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/SourceDetailHelper.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/SourceDetailHelper.cs index b08c94d482..81547143ad 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/SourceDetailHelper.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/SourceDetailHelper.cs @@ -12,7 +12,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Utilities; internal static class SourceDetailHelper { - internal static string UpdateRunSettingsFromSourceDetail(string runSettings, SourceDetail sourceDetail) + internal static string? UpdateRunSettingsFromSourceDetail(string runSettings, SourceDetail sourceDetail) { using var stream = new StringReader(runSettings); using var reader = XmlReader.Create(stream, XmlRunSettingsUtilities.ReaderSettings); @@ -23,7 +23,7 @@ internal static string UpdateRunSettingsFromSourceDetail(string runSettings, Sou InferRunSettingsHelper.UpdateTargetFramework(document, sourceDetail.Framework.ToString(), overwrite: true); InferRunSettingsHelper.UpdateTargetPlatform(document, sourceDetail.Architecture.ToString(), overwrite: true); - var updatedRunSettings = navigator.OuterXml; + var updatedRunSettings = navigator?.OuterXml; return updatedRunSettings; } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestCaseFilterDeterminer.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestCaseFilterDeterminer.cs index 12a6b44431..f89d0ffdd9 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestCaseFilterDeterminer.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestCaseFilterDeterminer.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Utilities; internal class TestCaseFilterDeterminer diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestSourcesUtility.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestSourcesUtility.cs index 35847271f2..d33f25f262 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestSourcesUtility.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Utilities/TestSourcesUtility.cs @@ -2,13 +2,12 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using Microsoft.VisualStudio.TestPlatform.ObjectModel; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Utilities; /// @@ -21,10 +20,10 @@ internal class TestSourcesUtility /// /// The test list. /// List of test Sources - internal static IEnumerable GetSources(Dictionary> adapterSourceMap) + internal static IEnumerable? GetSources(Dictionary?>? adapterSourceMap) { IEnumerable sources = new List(); - return adapterSourceMap?.Values?.Aggregate(sources, (current, enumerable) => current.Concat(enumerable)); + return adapterSourceMap?.Values?.Aggregate(sources, (current, enumerable) => enumerable is not null ? current.Concat(enumerable) : current); } /// @@ -32,7 +31,8 @@ internal static IEnumerable GetSources(Dictionary /// The test list. /// List of test Sources - internal static IEnumerable GetSources(IEnumerable tests) + [return: NotNullIfNotNull("tests")] + internal static IEnumerable? GetSources(IEnumerable? tests) { return tests?.Select(tc => tc.Source).Distinct(); } @@ -42,7 +42,7 @@ internal static IEnumerable GetSources(IEnumerable tests) /// /// The test list. /// List of test Sources - internal static string GetDefaultCodebasePath(Dictionary> adapterSourceMap) + internal static string? GetDefaultCodebasePath(Dictionary?> adapterSourceMap) { var source = GetSources(adapterSourceMap)?.FirstOrDefault(); return source != null ? Path.GetDirectoryName(source) : null; @@ -53,7 +53,7 @@ internal static string GetDefaultCodebasePath(Dictionary /// The test list. /// List of test Sources - internal static string GetDefaultCodebasePath(IEnumerable tests) + internal static string? GetDefaultCodebasePath(IEnumerable tests) { var source = GetSources(tests)?.FirstOrDefault(); return source != null ? Path.GetDirectoryName(source) : null; diff --git a/src/Microsoft.TestPlatform.Utilities/InferRunSettingsHelper.cs b/src/Microsoft.TestPlatform.Utilities/InferRunSettingsHelper.cs index aa709443e8..4c20e33a65 100644 --- a/src/Microsoft.TestPlatform.Utilities/InferRunSettingsHelper.cs +++ b/src/Microsoft.TestPlatform.Utilities/InferRunSettingsHelper.cs @@ -389,9 +389,14 @@ public static bool TryGetLegacySettingElements(string runsettingsXml, out Dictio /// /// The run settings xml string /// Environment Variables Dictionary - public static Dictionary? GetEnvironmentVariables(string runSettings) + public static Dictionary? GetEnvironmentVariables(string? runSettings) { Dictionary? environmentVariables = null; + if (runSettings is null) + { + return environmentVariables; + } + try { using var stream = new StringReader(runSettings); diff --git a/src/Microsoft.TestPlatform.Utilities/PublicAPI/PublicAPI.Shipped.txt b/src/Microsoft.TestPlatform.Utilities/PublicAPI/PublicAPI.Shipped.txt index 81ca6b842b..0fee4173bf 100644 --- a/src/Microsoft.TestPlatform.Utilities/PublicAPI/PublicAPI.Shipped.txt +++ b/src/Microsoft.TestPlatform.Utilities/PublicAPI/PublicAPI.Shipped.txt @@ -20,7 +20,7 @@ static Microsoft.VisualStudio.TestPlatform.Utilities.ClientUtilities.FixRelative static Microsoft.VisualStudio.TestPlatform.Utilities.CommandLineUtilities.SplitCommandLineIntoArguments(string! args, out string![]! arguments) -> bool static Microsoft.VisualStudio.TestPlatform.Utilities.InferRunSettingsHelper.AreRunSettingsCollectorsIncompatibleWithTestSettings(string? runsettings) -> bool static Microsoft.VisualStudio.TestPlatform.Utilities.InferRunSettingsHelper.FilterCompatibleSources(Microsoft.VisualStudio.TestPlatform.ObjectModel.Architecture chosenPlatform, Microsoft.VisualStudio.TestPlatform.ObjectModel.Architecture defaultArchitecture, Microsoft.VisualStudio.TestPlatform.ObjectModel.Framework! chosenFramework, System.Collections.Generic.IDictionary! sourcePlatforms, System.Collections.Generic.IDictionary! sourceFrameworks, out string! incompatibleSettingWarning) -> System.Collections.Generic.IEnumerable! -static Microsoft.VisualStudio.TestPlatform.Utilities.InferRunSettingsHelper.GetEnvironmentVariables(string! runSettings) -> System.Collections.Generic.Dictionary? +static Microsoft.VisualStudio.TestPlatform.Utilities.InferRunSettingsHelper.GetEnvironmentVariables(string? runSettings) -> System.Collections.Generic.Dictionary? static Microsoft.VisualStudio.TestPlatform.Utilities.InferRunSettingsHelper.IsTestSettingsEnabled(string? runsettingsXml) -> bool static Microsoft.VisualStudio.TestPlatform.Utilities.InferRunSettingsHelper.MakeRunsettingsCompatible(string? runsettingsXml) -> string? static Microsoft.VisualStudio.TestPlatform.Utilities.InferRunSettingsHelper.RemoveTargetPlatformElement(string? runsettingsXml) -> string? diff --git a/test/Microsoft.TestPlatform.Client.UnitTests/TestPlatformTests.cs b/test/Microsoft.TestPlatform.Client.UnitTests/TestPlatformTests.cs index 14f69fe448..1fb1b429ab 100644 --- a/test/Microsoft.TestPlatform.Client.UnitTests/TestPlatformTests.cs +++ b/test/Microsoft.TestPlatform.Client.UnitTests/TestPlatformTests.cs @@ -637,7 +637,7 @@ public TestableTestRuntimeProviderManager(ITestRuntimeProvider hostProvider) _hostProvider = hostProvider; } - public override ITestRuntimeProvider GetTestHostManagerByRunConfiguration(string runConfiguration, List _) + public override ITestRuntimeProvider GetTestHostManagerByRunConfiguration(string? runConfiguration, List? _) { return _hostProvider; } diff --git a/test/Microsoft.TestPlatform.Common.UnitTests/Hosting/TestHostProviderManagerTests.cs b/test/Microsoft.TestPlatform.Common.UnitTests/Hosting/TestHostProviderManagerTests.cs index 2c35b96773..9904266e30 100644 --- a/test/Microsoft.TestPlatform.Common.UnitTests/Hosting/TestHostProviderManagerTests.cs +++ b/test/Microsoft.TestPlatform.Common.UnitTests/Hosting/TestHostProviderManagerTests.cs @@ -96,7 +96,7 @@ public void GetDefaultTestHostManagerReturnsDotnetCoreHostManagerIfFrameworkIsNe var testHostManager = TestRuntimeProviderManager.Instance.GetTestHostManagerByRunConfiguration(runSettingsXml, null); - Assert.AreEqual(typeof(TestableTestHostManager), testHostManager.GetType()); + Assert.AreEqual(typeof(TestableTestHostManager), testHostManager!.GetType()); } [TestMethod] @@ -109,7 +109,7 @@ public void GetDefaultTestHostManagerReturnsASharedManagerIfDisableAppDomainIsFa " "); var testHostManager = TestRuntimeProviderManager.Instance.GetTestHostManagerByRunConfiguration(runSettingsXml, null); - testHostManager.Initialize(null, runSettingsXml); + testHostManager!.Initialize(null, runSettingsXml); Assert.IsNotNull(testHostManager); Assert.IsTrue(testHostManager.Shared, "Default TestHostManager must be shared if DisableAppDomain is false"); @@ -125,7 +125,7 @@ public void GetDefaultTestHostManagerReturnsANonSharedManagerIfDisableAppDomainI "true "); var testHostManager = TestRuntimeProviderManager.Instance.GetTestHostManagerByRunConfiguration(runSettingsXml, null); - testHostManager.Initialize(null, runSettingsXml); + testHostManager!.Initialize(null, runSettingsXml); Assert.IsNotNull(testHostManager); Assert.IsFalse(testHostManager.Shared, "Default TestHostManager must NOT be shared if DisableAppDomain is true"); diff --git a/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/ObjectModel/TestDiscoveryEventHandlerTests.cs b/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/ObjectModel/TestDiscoveryEventHandlerTests.cs index f69d97ec75..05a8daa530 100644 --- a/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/ObjectModel/TestDiscoveryEventHandlerTests.cs +++ b/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/ObjectModel/TestDiscoveryEventHandlerTests.cs @@ -26,8 +26,8 @@ public TestDiscoveryEventHandlerTests() [TestMethod] public void HandleDiscoveredTestShouldSendTestCasesToClient() { - _testDiscoveryEventHandler.HandleDiscoveredTests(null); - _mockClient.Verify(th => th.SendTestCases(null), Times.Once); + _testDiscoveryEventHandler.HandleDiscoveredTests(null!); + _mockClient.Verify(th => th.SendTestCases(null!), Times.Once); } [TestMethod] @@ -44,7 +44,7 @@ public void HandleDiscoveryCompleteShouldNotSendASeparateTestFoundMessageToClien { _testDiscoveryEventHandler.HandleDiscoveryComplete(new DiscoveryCompleteEventArgs(0, false), null); - _mockClient.Verify(th => th.SendTestCases(null), Times.Never); + _mockClient.Verify(th => th.SendTestCases(null!), Times.Never); } [TestMethod] diff --git a/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/ObjectModel/TestRunEventsHandlerTests.cs b/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/ObjectModel/TestRunEventsHandlerTests.cs index 72cf1e2044..58ba0c3bfd 100644 --- a/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/ObjectModel/TestRunEventsHandlerTests.cs +++ b/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/ObjectModel/TestRunEventsHandlerTests.cs @@ -25,15 +25,15 @@ public TestRunEventsHandlerTests() [TestMethod] public void HandleTestRunStatsChangeShouldSendTestRunStatisticsToClient() { - _testRunEventHandler.HandleTestRunStatsChange(null); - _mockClient.Verify(th => th.SendTestRunStatistics(null), Times.Once); + _testRunEventHandler.HandleTestRunStatsChange(null!); + _mockClient.Verify(th => th.SendTestRunStatistics(null!), Times.Once); } [TestMethod] public void HandleTestRunCompleteShouldInformClient() { - _testRunEventHandler.HandleTestRunComplete(null, null, null, null); - _mockClient.Verify(th => th.SendExecutionComplete(null, null, null, null), Times.Once); + _testRunEventHandler.HandleTestRunComplete(null!, null!, null!, null!); + _mockClient.Verify(th => th.SendExecutionComplete(null!, null!, null!, null!), Times.Once); } [TestMethod] diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Adapter/FrameworkHandleTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Adapter/FrameworkHandleTests.cs index e5c796b848..766f517a3e 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Adapter/FrameworkHandleTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Adapter/FrameworkHandleTests.cs @@ -21,7 +21,7 @@ public class FrameworkHandleTests public void EnableShutdownAfterTestRunShoudBeFalseByDefault() { var tec = GetTestExecutionContext(); - var frameworkHandle = new FrameworkHandle(null, new TestRunCache(100, TimeSpan.MaxValue, (s, r, ip) => { }), tec, null); + var frameworkHandle = new FrameworkHandle(null, new TestRunCache(100, TimeSpan.MaxValue, (s, r, ip) => { }), tec, null!); Assert.IsFalse(frameworkHandle.EnableShutdownAfterTestRun); } @@ -30,7 +30,7 @@ public void EnableShutdownAfterTestRunShoudBeFalseByDefault() public void EnableShutdownAfterTestRunShoudBeSetAppropriately() { var tec = GetTestExecutionContext(); - var frameworkHandle = new FrameworkHandle(null, new TestRunCache(100, TimeSpan.MaxValue, (s, r, ip) => { }), tec, null); + var frameworkHandle = new FrameworkHandle(null, new TestRunCache(100, TimeSpan.MaxValue, (s, r, ip) => { }), tec, null!); frameworkHandle.EnableShutdownAfterTestRun = true; @@ -41,10 +41,10 @@ public void EnableShutdownAfterTestRunShoudBeSetAppropriately() public void LaunchProcessWithDebuggerAttachedShouldThrowIfObjectIsDisposed() { var tec = GetTestExecutionContext(); - var frameworkHandle = new FrameworkHandle(null, new TestRunCache(100, TimeSpan.MaxValue, (s, r, ip) => { }), tec, null); + var frameworkHandle = new FrameworkHandle(null, new TestRunCache(100, TimeSpan.MaxValue, (s, r, ip) => { }), tec, null!); frameworkHandle.Dispose(); - Assert.ThrowsException(() => frameworkHandle.LaunchProcessWithDebuggerAttached(null, null, null, null)); + Assert.ThrowsException(() => frameworkHandle.LaunchProcessWithDebuggerAttached(null!, null!, null!, null!)); } // TODO: Enable method once we fix the "IsDebug" in TestExecutionContext @@ -52,12 +52,12 @@ public void LaunchProcessWithDebuggerAttachedShouldThrowIfObjectIsDisposed() public void LaunchProcessWithDebuggerAttachedShouldThrowIfNotInDebugContext() { var tec = GetTestExecutionContext(); - var frameworkHandle = new FrameworkHandle(null, new TestRunCache(100, TimeSpan.MaxValue, (s, r, ip) => { }), tec, null); + var frameworkHandle = new FrameworkHandle(null, new TestRunCache(100, TimeSpan.MaxValue, (s, r, ip) => { }), tec, null!); var isExceptionThrown = false; try { - frameworkHandle.LaunchProcessWithDebuggerAttached(null, null, null, null); + frameworkHandle.LaunchProcessWithDebuggerAttached(null!, null, null, null); } catch (InvalidOperationException exception) { @@ -81,7 +81,7 @@ public void LaunchProcessWithDebuggerAttachedShouldCallRunEventsHandler() tec, mockTestRunEventsHandler.Object); - frameworkHandle.LaunchProcessWithDebuggerAttached(null, null, null, null); + frameworkHandle.LaunchProcessWithDebuggerAttached(null!, null, null, null); mockTestRunEventsHandler.Verify(mt => mt.LaunchProcessWithDebuggerAttached(It.IsAny()), Times.Once); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Adapter/RunContextTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Adapter/RunContextTests.cs index 3b5c8560f7..8f9e3a1a42 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Adapter/RunContextTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Adapter/RunContextTests.cs @@ -24,7 +24,7 @@ public void GetTestCaseFilterShouldReturnNullIfFilterExpressionIsNull() { _runContext.FilterExpressionWrapper = null; - Assert.IsNull(_runContext.GetTestCaseFilter(null, (s) => null)); + Assert.IsNull(_runContext.GetTestCaseFilter(null, s => null)); } /// @@ -35,7 +35,7 @@ public void GetTestCaseFilterShouldNotThrowIfPropertyValueOnlyPassed() { _runContext.FilterExpressionWrapper = new FilterExpressionWrapper("Infinity"); - var filter = _runContext.GetTestCaseFilter(new List { "FullyQualifiedName" }, (s) => null); + var filter = _runContext.GetTestCaseFilter(new List { "FullyQualifiedName" }, s => null); Assert.IsNotNull(filter); } @@ -45,7 +45,7 @@ public void GetTestCaseFilterShouldNotThrowOnInvalidProperties() { _runContext.FilterExpressionWrapper = new FilterExpressionWrapper("highlyunlikelyproperty=unused"); - var filter = _runContext.GetTestCaseFilter(new List { "TestCategory" }, (s) => null); + var filter = _runContext.GetTestCaseFilter(new List { "TestCategory" }, s => null); Assert.IsNotNull(filter); } @@ -54,7 +54,7 @@ public void GetTestCaseFilterShouldNotThrowOnInvalidProperties() public void GetTestCaseFilterShouldReturnTestCaseFilter() { _runContext.FilterExpressionWrapper = new FilterExpressionWrapper("TestCategory=Important"); - var filter = _runContext.GetTestCaseFilter(new List { "TestCategory" }, (s) => null); + var filter = _runContext.GetTestCaseFilter(new List { "TestCategory" }, s => null); Assert.IsNotNull(filter); Assert.AreEqual("TestCategory=Important", filter.TestCaseFilterValue); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/AttachmentsProcessing/TestRunAttachmentsProcessingManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/AttachmentsProcessing/TestRunAttachmentsProcessingManagerTests.cs index d2d9e3749d..324c3532b0 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/AttachmentsProcessing/TestRunAttachmentsProcessingManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/AttachmentsProcessing/TestRunAttachmentsProcessingManagerTests.cs @@ -878,7 +878,7 @@ private void VerifyMetrics(int inputCount, int outputCount, string status = "Com private void VerifyCompleteEvent(bool isCanceled, bool containsError, params AttachmentSet[] expectedSets) { _mockEventsHandler.Verify(h => h.HandleTestRunAttachmentsProcessingComplete( - It.Is(a => a.IsCanceled == isCanceled && (a.Error != null) == containsError), + It.Is(a => a.IsCanceled == isCanceled && a.Error != null == containsError), It.Is>(c => c.Count == expectedSets.Length && expectedSets.All(e => c.Contains(e))))); } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyDiscoveryManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyDiscoveryManagerTests.cs index e006925c1a..879ef89150 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyDiscoveryManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyDiscoveryManagerTests.cs @@ -44,7 +44,7 @@ public void DiscoverTestsShouldCallInitialize() () => manualResetEvent.Set()); var discoveryCriteria = new DiscoveryCriteria(new[] { "test.dll" }, 1, string.Empty); - _inProcessProxyDiscoveryManager.DiscoverTests(discoveryCriteria, null); + _inProcessProxyDiscoveryManager.DiscoverTests(discoveryCriteria, null!); Assert.IsTrue(manualResetEvent.WaitOne(5000), "DiscoverTests should call Initialize"); } @@ -62,7 +62,7 @@ public void DiscoverTestsShouldUpdateTestPluginCacheWithExtensionsReturnByTestHo expectedResult.Add(path); var discoveryCriteria = new DiscoveryCriteria(new[] { "test.dll" }, 1, string.Empty); - _inProcessProxyDiscoveryManager.DiscoverTests(discoveryCriteria, null); + _inProcessProxyDiscoveryManager.DiscoverTests(discoveryCriteria, null!); Assert.IsTrue(manualResetEvent.WaitOne(5000), "DiscoverTests should call Initialize"); CollectionAssert.AreEquivalent(expectedResult, TestPluginCache.Instance.GetExtensionPaths(string.Empty)); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs index 31b3ba61de..c7bf485f59 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs @@ -42,7 +42,7 @@ public void StartTestRunShouldCallInitialize() { var testRunCriteria = new TestRunCriteria(new List { "source.dll" }, 10); var mockTestMessageEventHandler = new Mock(); - _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null); + _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null!); _mockExecutionManager.Verify(o => o.Initialize(Enumerable.Empty(), It.IsAny()), Times.Once, "StartTestRun should call Initialize if not already initialized"); } @@ -56,7 +56,7 @@ public void StartTestRunShouldUpdateTestPlauginCacheWithExtensionsReturnByTestHo expectedResult.Add(path); var testRunCriteria = new TestRunCriteria(new List { "source.dll" }, 10); - _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null); + _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null!); CollectionAssert.AreEquivalent(expectedResult, TestPluginCache.Instance.GetExtensionPaths(string.Empty)); } @@ -70,7 +70,7 @@ public void StartTestRunShouldCallExecutionManagerStartTestRunWithAdapterSourceM _mockExecutionManager.Setup(o => o.StartTestRun(testRunCriteria.AdapterSourceMap, null, testRunCriteria.TestRunSettings, It.IsAny(), null, null)).Callback( () => manualResetEvent.Set()); - _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null); + _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null!); Assert.IsTrue(manualResetEvent.WaitOne(5000), "IExecutionManager.StartTestRun should get called"); } @@ -82,7 +82,7 @@ public void StartTestRunShouldAllowRuntimeProviderToUpdateAdapterSource() _mockTestHostManager.Setup(hm => hm.GetTestSources(testRunCriteria.Sources)).Returns(testRunCriteria.Sources); - _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null); + _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null!); _mockTestHostManager.Verify(hm => hm.GetTestSources(testRunCriteria.Sources), Times.Once); } @@ -98,7 +98,7 @@ public void StartTestRunShouldCallExecutionManagerStartTestRunWithTestCase() _mockExecutionManager.Setup(o => o.StartTestRun(testRunCriteria.Tests, null, testRunCriteria.TestRunSettings, It.IsAny(), null, null)).Callback( () => manualResetEvent.Set()); - _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null); + _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null!); Assert.IsTrue(manualResetEvent.WaitOne(5000), "IExecutionManager.StartTestRun should get called"); } @@ -121,7 +121,7 @@ public void StartTestRunShouldUpdateTestCaseSourceIfTestCaseSourceDiffersFromTes _inProcessProxyExecutionManager = new InProcessProxyExecutionManager(_mockTestHostManager.Object, _mockTestHostManagerFactory.Object); - _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null); + _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null!); Assert.IsTrue(manualResetEvent.WaitOne(5000), "IExecutionManager.StartTestRun should get called"); _mockExecutionManager.Verify(o => o.StartTestRun(testRunCriteria.Tests, inputSource.FirstOrDefault(), testRunCriteria.TestRunSettings, It.IsAny(), null, null)); @@ -143,7 +143,7 @@ public void StartTestRunShouldNotUpdateTestCaseSourceIfTestCaseSourceDiffersFrom _mockExecutionManager.Setup(o => o.StartTestRun(testRunCriteria.Tests, null, testRunCriteria.TestRunSettings, It.IsAny(), null, null)) .Callback(() => manualResetEvent.Set()); - _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null); + _inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null!); Assert.IsTrue(manualResetEvent.WaitOne(5000), "IExecutionManager.StartTestRun should get called"); _mockExecutionManager.Verify(o => o.StartTestRun(testRunCriteria.Tests, null, testRunCriteria.TestRunSettings, It.IsAny(), null, null)); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/Parallel/ParallelOperationManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/Parallel/ParallelOperationManagerTests.cs index c1b1982325..0d55a40695 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/Parallel/ParallelOperationManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/Parallel/ParallelOperationManagerTests.cs @@ -25,7 +25,7 @@ public void OperationManagerShouldRunOnlyMaximumParallelLevelOfWorkInParallelEve // Create more workloads than our parallel level so we can observe that the maximum parallel level is reached but not more var workloads = Enumerable.Range(1, maxParallelLevel + 2) - .Select(i => new ProviderSpecificWorkload(new SampleWorkload { Id = i }, provider: null)) + .Select(i => new ProviderSpecificWorkload(new SampleWorkload { Id = i }, provider: null!)) .ToList(); var eventHandler = new SampleHandler(); @@ -75,7 +75,7 @@ public void OperationManagerShouldCreateOnlyAsManyParallelWorkersAsThereAreWorkl // Create less workloads than our parallel level so we can observe that only as many slots are created as there are workloads. var workloads = Enumerable.Range(1, 2) - .Select(i => new ProviderSpecificWorkload(new SampleWorkload { Id = i }, provider: null)) + .Select(i => new ProviderSpecificWorkload(new SampleWorkload { Id = i }, provider: null!)) .ToList(); var eventHandler = new SampleHandler(); @@ -109,7 +109,7 @@ public void OperationManagerShouldCreateAsManyMaxParallelLevel() // Create less workloads than our parallel level so we can observe that only as many slots are created as there are workloads. var workloads = Enumerable.Range(1, 2) - .Select(i => new ProviderSpecificWorkload(new SampleWorkload { Id = i }, provider: null)) + .Select(i => new ProviderSpecificWorkload(new SampleWorkload { Id = i }, provider: null!)) .ToList(); var eventHandler = new SampleHandler(); @@ -148,7 +148,7 @@ public void OperationManagerMovesToTheNextWorkloadOnlyWhenRunNextWorkIsCalled() // Create more workloads than our parallel level so we can observe that when one workload is finished, calling RunNextWork will move on // to the next workload. var workloads = Enumerable.Range(1, maxParallelLevel + 3) - .Select(i => new ProviderSpecificWorkload(new SampleWorkload { Id = i }, provider: null)) + .Select(i => new ProviderSpecificWorkload(new SampleWorkload { Id = i }, provider: null!)) .ToList(); var eventHandler = new SampleHandler(); @@ -197,7 +197,7 @@ public void OperationManagerRunsAnOperationOnAllActiveManagersWhenDoActionOnAllM // Create more workloads than the parallel level so we can go past max parallel level of active workers and simulate that we // are aborting in the middle of a run. var workloads = Enumerable.Range(1, maxParallelLevel + 3) - .Select(i => new ProviderSpecificWorkload(new SampleWorkload { Id = i }, provider: null)) + .Select(i => new ProviderSpecificWorkload(new SampleWorkload { Id = i }, provider: null!)) .ToList(); var parallelOperationManager = new ParallelOperationManager(createNewManager, maxParallelLevel); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/Parallel/ParallelProxyExecutionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/Parallel/ParallelProxyExecutionManagerTests.cs index 1a1c13dcc8..2d398e9a7f 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/Parallel/ParallelProxyExecutionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/Parallel/ParallelProxyExecutionManagerTests.cs @@ -189,7 +189,7 @@ public void HandlePartialRunCompleteShouldCreateNewProxyExecutionManagerIfDataCo // act // Tell the manager that completedManager finished work, and that it should progress to next work - parallelExecutionManager.HandlePartialRunComplete(completedManager.Object, completeArgs, null, null, null); + parallelExecutionManager.HandlePartialRunComplete(completedManager.Object, completeArgs, null!, null!, null!); // assert // We created 2 managers 1 for the original work and another one diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyBaseManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyBaseManagerTests.cs index a87d783b83..63b59edee8 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyBaseManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyBaseManagerTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Net; using System.Threading; using System.Threading.Tasks; @@ -63,6 +64,7 @@ public ProxyBaseManagerTests() .Returns(Task.FromResult(true)); } + [MemberNotNull(nameof(_testRequestSender), nameof(_testRequestSender))] private void SetupAndInitializeTestRequestSender() { var connectionInfo = new TestHostConnectionInfo diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs index adecf8a5fb..ba9100f25f 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs @@ -67,7 +67,7 @@ public void DiscoverTestsShouldNotInitializeExtensionsOnNoExtensions() _mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); - _discoveryManager.DiscoverTests(_discoveryCriteria, null); + _discoveryManager.DiscoverTests(_discoveryCriteria, null!); _mockRequestSender.Verify(s => s.InitializeDiscovery(It.IsAny>()), Times.Never); } @@ -184,7 +184,7 @@ public void DiscoverTestsShouldInitializeExtensionsIfPresent() _mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); _mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "c:\\e1.dll", "c:\\e2.dll" }); - _discoveryManager.DiscoverTests(_discoveryCriteria, null); + _discoveryManager.DiscoverTests(_discoveryCriteria, null!); // Also verify that we have waited for client connection. _mockRequestSender.Verify(s => s.InitializeDiscovery(extensions), Times.Once); @@ -227,7 +227,7 @@ public void DiscoverTestsShouldQueryTestHostManagerForExtensions() _mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); _mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "he1.dll", "c:\\e1.dll" }); - _discoveryManager.DiscoverTests(_discoveryCriteria, null); + _discoveryManager.DiscoverTests(_discoveryCriteria, null!); _mockRequestSender.Verify(s => s.InitializeDiscovery(new[] { "he1.dll", "c:\\e1.dll" }), Times.Once); } @@ -249,7 +249,7 @@ public void DiscoverTestsShouldPassAdapterToTestHostManagerFromTestPluginCacheEx _mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); var expectedResult = TestPluginCache.Instance.GetExtensionPaths(string.Empty); - _discoveryManager.DiscoverTests(_discoveryCriteria, null); + _discoveryManager.DiscoverTests(_discoveryCriteria, null!); _mockTestHostManager.Verify(th => th.GetTestPlatformExtensions(It.IsAny>(), expectedResult), Times.Once); } @@ -278,7 +278,7 @@ public void DiscoverTestsShouldNotIntializeTestHost() _mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); // Act. - _discoveryManager.DiscoverTests(_discoveryCriteria, null); + _discoveryManager.DiscoverTests(_discoveryCriteria, null!); _mockRequestSender.Verify(s => s.InitializeCommunication(), Times.Once); _mockTestHostManager.Verify(thl => thl.LaunchTestHostAsync(It.IsAny(), It.IsAny()), Times.Once); @@ -378,7 +378,7 @@ public void DiscoverTestsShouldInitiateServerDiscoveryLoop() _mockFileHelper.Setup(fh => fh.Exists(It.IsAny())).Returns(true); // Act. - _discoveryManager.DiscoverTests(_discoveryCriteria, null); + _discoveryManager.DiscoverTests(_discoveryCriteria, null!); // Assert. _mockRequestSender.Verify(s => s.DiscoverTests(It.IsAny(), _discoveryManager), Times.Once); @@ -534,7 +534,7 @@ public void StartTestRunShouldAttemptToTakeProxyFromPoolIfProxyIsNull() _discoveryCriteria.RunSettings, _mockRequestData.Object); - return proxyOperationManager; + return proxyOperationManager!; }; var testDiscoveryManager = new ProxyDiscoveryManager( @@ -743,7 +743,7 @@ private void InvokeAndVerifyDiscoverTests(bool skipDefaultAdapters) var expectedResult = TestPluginCache.Instance.GetExtensionPaths(TestPlatformConstants.TestAdapterEndsWithPattern, skipDefaultAdapters); _discoveryManager.Initialize(skipDefaultAdapters); - _discoveryManager.DiscoverTests(_discoveryCriteria, null); + _discoveryManager.DiscoverTests(_discoveryCriteria, null!); _mockRequestSender.Verify(s => s.InitializeDiscovery(expectedResult), Times.Once); } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs index 9d763ed183..defc2bcedc 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs @@ -65,7 +65,7 @@ public void StartTestRunShouldNotInitializeExtensionsOnNoExtensions() _mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); - _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null); + _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null!); _mockRequestSender.Verify(s => s.InitializeExecution(It.IsAny>()), Times.Never); } @@ -158,7 +158,7 @@ public void StartTestRunShouldInitializeExtensionsIfPresent() _mockTestHostManager.Setup(x => x.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())) .Returns(extensions); - _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null); + _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null!); // Also verify that we have waited for client connection. _mockRequestSender.Verify(s => s.InitializeExecution(extensions), Times.Once); @@ -178,7 +178,7 @@ public void StartTestRunShouldQueryTestHostManagerForExtensions() _mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); _mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "he1.dll", "c:\\e1.dll" }); - _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null); + _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null!); _mockRequestSender.Verify(s => s.InitializeExecution(new[] { "he1.dll", "c:\\e1.dll" }), Times.Once); } @@ -200,7 +200,7 @@ public void StartTestRunShouldPassAdapterToTestHostManagerFromTestPluginCacheExt _mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); var expectedResult = TestPluginCache.Instance.GetExtensionPaths(string.Empty); - _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null); + _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null!); _mockTestHostManager.Verify(th => th.GetTestPlatformExtensions(It.IsAny>(), expectedResult), Times.Once); } @@ -228,7 +228,7 @@ public void StartTestRunShouldIntializeTestHost() _mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); _mockFileHelper.Setup(fh => fh.Exists(It.IsAny())).Returns(true); - _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null); + _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null!); _mockRequestSender.Verify(s => s.InitializeCommunication(), Times.Once); _mockTestHostManager.Verify(thl => thl.LaunchTestHostAsync(It.IsAny(), It.IsAny()), Times.Once); @@ -262,7 +262,7 @@ public void StartTestRunShouldInitializeExtensionsIfTestHostIsNotShared() _mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); _mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "x.dll" }); - _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null); + _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null!); _mockRequestSender.Verify(s => s.InitializeExecution(It.IsAny>()), Times.Once); } @@ -437,7 +437,7 @@ public void StartTestRunShouldInitiateTestRunForSourcesThroughTheServer() .Callback( (TestRunCriteriaWithSources criteria, IInternalTestRunEventsHandler sink) => testRunCriteriaPassed = criteria); - _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null); + _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null!); Assert.IsNotNull(testRunCriteriaPassed); CollectionAssert.AreEqual(_mockTestRunCriteria.Object.AdapterSourceMap.Keys, testRunCriteriaPassed.AdapterSourceMap.Keys); @@ -460,7 +460,7 @@ public void StartTestRunShouldInitiateTestRunForTestsThroughTheServer() new List { new TestCase("A.C.M", new Uri("executor://dummy"), "source.dll") }, 10); - _testExecutionManager.StartTestRun(runCriteria.Object, null); + _testExecutionManager.StartTestRun(runCriteria.Object, null!); Assert.IsNotNull(testRunCriteriaPassed); CollectionAssert.AreEqual(runCriteria.Object.Tests.ToList(), testRunCriteriaPassed.Tests.ToList()); @@ -739,7 +739,7 @@ public void StartTestRunShouldAttemptToTakeProxyFromPoolIfProxyIsNull() string.Empty, _mockRequestData.Object); - return proxyOperationManager; + return proxyOperationManager!; }; var testExecutionManager = new ProxyExecutionManager( @@ -807,7 +807,7 @@ private void InvokeAndVerifyStartTestRun(bool skipDefaultAdapters) var expectedResult = TestPluginCache.Instance.GetExtensionPaths(TestPlatformConstants.TestAdapterEndsWithPattern, skipDefaultAdapters); _testExecutionManager.Initialize(skipDefaultAdapters); - _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null); + _testExecutionManager.StartTestRun(_mockTestRunCriteria.Object, null!); _mockRequestSender.Verify(s => s.InitializeExecution(expectedResult), Times.Once); } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DataCollectionTestRunEventsHandlerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DataCollectionTestRunEventsHandlerTests.cs index 26ee69e0aa..68c8be5313 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DataCollectionTestRunEventsHandlerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DataCollectionTestRunEventsHandlerTests.cs @@ -47,7 +47,7 @@ public void HandleLogMessageShouldSendMessageToBaseTestRunEventsHandler() public void HandleRawMessageShouldSendMessageToBaseTestRunEventsHandler() { _mockDataSerializer.Setup(x => x.DeserializeMessage(It.IsAny())).Returns(new Message() { MessageType = MessageType.BeforeTestRunStart }); - _testRunEventHandler.HandleRawMessage(null); + _testRunEventHandler.HandleRawMessage(null!); _baseTestRunEventsHandler.Verify(th => th.HandleRawMessage(null), Times.AtLeast(1)); } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DotnetDataCollectionLauncherTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DotnetDataCollectionLauncherTests.cs index d677509753..a194d98525 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DotnetDataCollectionLauncherTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DotnetDataCollectionLauncherTests.cs @@ -29,6 +29,7 @@ public DotnetDataCollectionLauncherTests() { _mockFileHelper = new Mock(); _mockProcessHelper = new Mock(); + _mockProcessHelper.Setup(x => x.GetCurrentProcessFileName()).Returns("dotnet"); _mockMessageLogger = new Mock(); _dataCollectionLauncher = new DotnetDataCollectionLauncher(_mockProcessHelper.Object, _mockFileHelper.Object, _mockMessageLogger.Object); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/InProcDataCollectorTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/InProcDataCollectorTests.cs index 4ca616aad1..e3ae6c7b20 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/InProcDataCollectorTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/InProcDataCollectorTests.cs @@ -41,7 +41,7 @@ public void InProcDataCollectorShouldNotThrowExceptionIfInvalidAssemblyIsProvide _inProcDataCollector = new InProcDataCollector( string.Empty, string.Empty, - null, + null!, string.Empty, _assemblyLoadContext.Object, TestPluginCache.Instance); @@ -58,7 +58,7 @@ public void InProcDataCollectorShouldNotThrowExceptionIfAssemblyDoesNotContainAn _inProcDataCollector = new InProcDataCollector( string.Empty, string.Empty, - null, + null!, string.Empty, _assemblyLoadContext.Object, TestPluginCache.Instance); @@ -76,7 +76,7 @@ public void InProcDataCollectorShouldInitializeIfAssemblyContainsAnyInProcDataCo _inProcDataCollector = new InProcDataCollector( string.Empty, - typeInfo.AssemblyQualifiedName, + typeInfo.AssemblyQualifiedName!, typeInfo, string.Empty, _assemblyLoadContext.Object, diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs index 14210b34c3..7e46fa96b3 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs @@ -178,7 +178,7 @@ public void BeforeTestRunStartShouldReturnDataCollectorParameters() x => x.SendBeforeTestRunStartAndGetResult(It.IsAny(), sourceList, false, It.IsAny()), Times.Once); Assert.IsNotNull(result); Assert.AreEqual(res.DataCollectionEventsPort, result.DataCollectionEventsPort); - Assert.AreEqual(res.EnvironmentVariables.Count, result.EnvironmentVariables.Count); + Assert.AreEqual(res.EnvironmentVariables.Count, result.EnvironmentVariables!.Count); } [TestMethod] @@ -192,7 +192,7 @@ public void BeforeTestRunStartsShouldInvokeRunEventsHandlerIfExceptionIsThrown() var result = _proxyDataCollectionManager.BeforeTestRunStart(true, true, mockRunEventsHandler.Object); mockRunEventsHandler.Verify(eh => eh.HandleLogMessage(TestMessageLevel.Error, It.IsRegex("Exception of type 'System.Exception' was thrown..*")), Times.Once); - Assert.AreEqual(0, result.EnvironmentVariables.Count); + Assert.AreEqual(0, result.EnvironmentVariables!.Count); Assert.IsFalse(result.AreTestCaseLevelEventsRequired); Assert.AreEqual(0, result.DataCollectionEventsPort); } @@ -212,7 +212,7 @@ public void SendBeforeTestRunStartAndGetResultShouldBeInvokedWithCorrectTestSour x => x.SendBeforeTestRunStartAndGetResult(string.Empty, testSources, false, It.IsAny()), Times.Once); Assert.IsNotNull(result); Assert.AreEqual(res.DataCollectionEventsPort, result.DataCollectionEventsPort); - Assert.AreEqual(res.EnvironmentVariables.Count, result.EnvironmentVariables.Count); + Assert.AreEqual(res.EnvironmentVariables.Count, result.EnvironmentVariables!.Count); } [TestMethod] @@ -238,7 +238,7 @@ public void AfterTestRunEndShouldReturnAttachments(bool telemetryOptedIn) var result = _proxyDataCollectionManager.AfterTestRunEnd(false, null); Assert.IsNotNull(result); - Assert.AreEqual(1, result.Attachments.Count); + Assert.AreEqual(1, result.Attachments!.Count); Assert.IsNotNull(result.Attachments[0]); Assert.AreEqual(dispName, result.Attachments[0].DisplayName); Assert.AreEqual(uri, result.Attachments[0].Uri); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscovererEnumeratorTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscovererEnumeratorTests.cs index 3adcdc2060..b55f118bde 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscovererEnumeratorTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscovererEnumeratorTests.cs @@ -231,7 +231,7 @@ public void LoadTestsShouldCallIntoADiscovererThatMatchesTheSources() // Also validate that the right set of arguments were passed on to the discoverer. CollectionAssert.AreEqual(sources, ManagedDllTestDiscoverer.Sources!.ToList()); Assert.AreEqual(_runSettingsMock.Object, DllTestDiscoverer.DiscoveryContext!.RunSettings); - Assert.AreEqual(testCaseFilter, ((DiscoveryContext)DllTestDiscoverer.DiscoveryContext).FilterExpressionWrapper.FilterString); + Assert.AreEqual(testCaseFilter, ((DiscoveryContext)DllTestDiscoverer.DiscoveryContext).FilterExpressionWrapper!.FilterString); Assert.AreEqual(_messageLoggerMock.Object, DllTestDiscoverer.MessageLogger); Assert.IsNotNull(DllTestDiscoverer.DiscoverySink); } @@ -273,13 +273,13 @@ public void LoadTestsShouldCallIntoMultipleDiscoverersThatMatchesTheSources() // Also validate that the right set of arguments were passed on to the discoverer. CollectionAssert.AreEqual(dllsources, ManagedDllTestDiscoverer.Sources!.ToList()); Assert.AreEqual(runSettings, DllTestDiscoverer.DiscoveryContext!.RunSettings); - Assert.AreEqual(testCaseFilter, ((DiscoveryContext)DllTestDiscoverer.DiscoveryContext).FilterExpressionWrapper.FilterString); + Assert.AreEqual(testCaseFilter, ((DiscoveryContext)DllTestDiscoverer.DiscoveryContext).FilterExpressionWrapper!.FilterString); Assert.AreEqual(_messageLoggerMock.Object, DllTestDiscoverer.MessageLogger); Assert.IsNotNull(DllTestDiscoverer.DiscoverySink); CollectionAssert.AreEqual(jsonsources, JsonTestDiscoverer.Sources!.ToList()); Assert.AreEqual(runSettings, JsonTestDiscoverer.DiscoveryContext!.RunSettings); - Assert.AreEqual(testCaseFilter, ((DiscoveryContext)JsonTestDiscoverer.DiscoveryContext).FilterExpressionWrapper.FilterString); + Assert.AreEqual(testCaseFilter, ((DiscoveryContext)JsonTestDiscoverer.DiscoveryContext).FilterExpressionWrapper!.FilterString); Assert.AreEqual(_messageLoggerMock.Object, JsonTestDiscoverer.MessageLogger); Assert.IsNotNull(JsonTestDiscoverer.DiscoverySink); } @@ -314,7 +314,7 @@ public void LoadTestsShouldCallIntoOtherDiscoverersWhenCreatingOneFails() // Also validate that the right set of arguments were passed on to the discoverer. CollectionAssert.AreEqual(new List { sources[1] }, ManagedDllTestDiscoverer.Sources!.ToList()); Assert.AreEqual(runSettings, DllTestDiscoverer.DiscoveryContext!.RunSettings); - Assert.AreEqual(testCaseFilter, ((DiscoveryContext)DllTestDiscoverer.DiscoveryContext).FilterExpressionWrapper.FilterString); + Assert.AreEqual(testCaseFilter, ((DiscoveryContext)DllTestDiscoverer.DiscoveryContext).FilterExpressionWrapper!.FilterString); Assert.AreEqual(_messageLoggerMock.Object, DllTestDiscoverer.MessageLogger); Assert.IsNotNull(DllTestDiscoverer.DiscoverySink); } @@ -349,7 +349,7 @@ public void LoadTestsShouldCallIntoOtherDiscoverersEvenIfDiscoveryInOneFails() // Also validate that the right set of arguments were passed on to the discoverer. CollectionAssert.AreEqual(new List { sources[1] }, ManagedDllTestDiscoverer.Sources!.ToList()); Assert.AreEqual(runSettings, DllTestDiscoverer.DiscoveryContext!.RunSettings); - Assert.AreEqual(testCaseFilter, ((DiscoveryContext)DllTestDiscoverer.DiscoveryContext).FilterExpressionWrapper.FilterString); + Assert.AreEqual(testCaseFilter, ((DiscoveryContext)DllTestDiscoverer.DiscoveryContext).FilterExpressionWrapper!.FilterString); Assert.AreEqual(_messageLoggerMock.Object, DllTestDiscoverer.MessageLogger); Assert.IsNotNull(DllTestDiscoverer.DiscoverySink); @@ -524,13 +524,13 @@ public void LoadTestsShouldIterateOverAllExtensionsInTheMapAndDiscoverTests() // Also validate that the right set of arguments were passed on to the discoverer. CollectionAssert.AreEqual(dllsources, ManagedDllTestDiscoverer.Sources!.ToList()); Assert.AreEqual(runSettings, DllTestDiscoverer.DiscoveryContext!.RunSettings); - Assert.AreEqual(testCaseFilter, ((DiscoveryContext)DllTestDiscoverer.DiscoveryContext).FilterExpressionWrapper.FilterString); + Assert.AreEqual(testCaseFilter, ((DiscoveryContext)DllTestDiscoverer.DiscoveryContext).FilterExpressionWrapper!.FilterString); Assert.AreEqual(_messageLoggerMock.Object, DllTestDiscoverer.MessageLogger); Assert.IsNotNull(DllTestDiscoverer.DiscoverySink); CollectionAssert.AreEqual(jsonsources, JsonTestDiscoverer.Sources!.ToList()); Assert.AreEqual(runSettings, JsonTestDiscoverer.DiscoveryContext!.RunSettings); - Assert.AreEqual(testCaseFilter, ((DiscoveryContext)JsonTestDiscoverer.DiscoveryContext).FilterExpressionWrapper.FilterString); + Assert.AreEqual(testCaseFilter, ((DiscoveryContext)JsonTestDiscoverer.DiscoveryContext).FilterExpressionWrapper!.FilterString); Assert.AreEqual(_messageLoggerMock.Object, JsonTestDiscoverer.MessageLogger); Assert.IsNotNull(JsonTestDiscoverer.DiscoverySink); } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscoveryContextTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscoveryContextTests.cs index 03edef91dc..174ae2b1d5 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscoveryContextTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscoveryContextTests.cs @@ -27,7 +27,7 @@ public void GetTestCaseFilterShouldReturnNullIfFilterExpressionIsNull() { _discoveryContext.FilterExpressionWrapper = null; - Assert.IsNull(_discoveryContext.GetTestCaseFilter(null, (s) => null)); + Assert.IsNull(_discoveryContext.GetTestCaseFilter(null, s => null)); } /// @@ -38,7 +38,7 @@ public void GetTestCaseFilterShouldNotThrowIfPropertyValueOnlyPassed() { _discoveryContext.FilterExpressionWrapper = new FilterExpressionWrapper("Infinity"); - var filter = _discoveryContext.GetTestCaseFilter(new List { "FullyQualifiedName" }, (s) => null); + var filter = _discoveryContext.GetTestCaseFilter(new List { "FullyQualifiedName" }, s => null); Assert.IsNotNull(filter); } @@ -51,7 +51,7 @@ public void GetTestCaseFilterShouldNotThrowOnInvalidProperties() { _discoveryContext.FilterExpressionWrapper = new FilterExpressionWrapper("highlyunlikelyproperty=unused"); - var filter = _discoveryContext.GetTestCaseFilter(new List { "TestCategory" }, (s) => null); + var filter = _discoveryContext.GetTestCaseFilter(new List { "TestCategory" }, s => null); Assert.IsNotNull(filter); } @@ -64,7 +64,7 @@ public void GetTestCaseFilterShouldReturnTestCaseFilter() { _discoveryContext.FilterExpressionWrapper = new FilterExpressionWrapper("TestCategory=Important"); - var filter = _discoveryContext.GetTestCaseFilter(new List { "TestCategory" }, (s) => null); + var filter = _discoveryContext.GetTestCaseFilter(new List { "TestCategory" }, s => null); Assert.IsNotNull(filter); Assert.AreEqual("TestCategory=Important", filter.TestCaseFilterValue); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs index 37bb3f7bca..04c8f56615 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/BaseRunTestsTests.cs @@ -952,7 +952,7 @@ public TestableBaseRunTests( /// /// Gets the run settings. /// - public string GetRunSettings => RunSettings; + public string? GetRunSettings => RunSettings; /// /// Gets the test execution context. diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestLoggerManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestLoggerManagerTests.cs index ec6e3e7f97..89342d6e8d 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestLoggerManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestLoggerManagerTests.cs @@ -50,9 +50,9 @@ public void TestCleanup() public void TryGetUriFromFriendlyNameShouldReturnUriIfLoggerIsAdded() { var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.TryGetUriFromFriendlyName("TestLoggerExtension", out var uri); - Assert.AreEqual(uri.ToString(), new Uri(_loggerUri).ToString()); + Assert.AreEqual(uri?.ToString(), new Uri(_loggerUri).ToString()); } [TestMethod] @@ -67,7 +67,7 @@ public void TryGetUriFromFriendlyNameShouldNotReturnUriIfLoggerIsNotAdded() public void GetResultsDirectoryShouldReturnNullIfRunSettingsIsNull() { var testLoggerManager = new DummyTestLoggerManager(); - string result = testLoggerManager.GetResultsDirectory(null); + var result = testLoggerManager.GetResultsDirectory(null); Assert.IsNull(result); } @@ -85,7 +85,7 @@ public void GetResultsDirectoryShouldReadResultsDirectoryFromSettingsIfSpecified "; var testLoggerManager = new DummyTestLoggerManager(); - string result = testLoggerManager.GetResultsDirectory(runSettingsXml); + var result = testLoggerManager.GetResultsDirectory(runSettingsXml); Assert.AreEqual(0, string.Compare("DummyTestResultsFolder", result)); } @@ -102,7 +102,7 @@ public void GetResultsDirectoryShouldReturnDefaultPathIfResultsDirectoryIsNotPro "; var testLoggerManager = new DummyTestLoggerManager(); - string result = testLoggerManager.GetResultsDirectory(runSettingsXml); + var result = testLoggerManager.GetResultsDirectory(runSettingsXml); Assert.AreEqual(0, string.Compare(Constants.DefaultResultsDirectory, result)); } @@ -122,7 +122,7 @@ public void GetTargetFrameworkShouldReturnFrameworkProvidedInRunSettings() var testLoggerManager = new DummyTestLoggerManager(); var framework = testLoggerManager.GetTargetFramework(runSettingsXml); - Assert.AreEqual(".NETFramework,Version=v4.5", framework.Name); + Assert.AreEqual(".NETFramework,Version=v4.5", framework?.Name); } [TestMethod] @@ -131,7 +131,7 @@ public void HandleTestRunMessageShouldInvokeTestRunMessageHandlerOfLoggers() s_counter = 0; WaitHandle.Reset(); var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.HandleTestRunMessage(new TestRunMessageEventArgs(TestMessageLevel.Informational, "TestRunMessage")); @@ -146,7 +146,7 @@ public void HandleTestRunMessageShouldNotInvokeTestRunMessageHandlerOfLoggersIfD s_counter = 0; WaitHandle.Reset(); var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.Dispose(); @@ -162,7 +162,7 @@ public void HandleTestRunCompleteShouldInvokeTestRunCompleteHandlerOfLoggers() WaitHandle.Reset(); // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.HandleTestRunComplete(new TestRunCompleteEventArgs(null, false, false, null, null, null, new TimeSpan())); @@ -178,7 +178,7 @@ public void HandleTestRunCompleteShouldNotInvokeTestRunCompleteHandlerOfLoggersI WaitHandle.Reset(); // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.Dispose(); @@ -194,7 +194,7 @@ public void HandleTestRunCompleteShouldDisposeLoggerManager() WaitHandle.Reset(); // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.HandleTestRunComplete(new TestRunCompleteEventArgs(null, false, false, null, null, null, new TimeSpan())); @@ -210,7 +210,7 @@ public void HandleTestRunStatsChangeShouldInvokeTestRunChangedHandlerOfLoggers() WaitHandle.Reset(); // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.HandleTestRunStatsChange( @@ -237,7 +237,7 @@ public void HandleTestRunStatsChangeShouldNotInvokeTestRunChangedHandlerOfLogger WaitHandle.Reset(); // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.Dispose(); @@ -262,7 +262,7 @@ public void AddLoggerShouldNotThrowExceptionIfUriIsNull() { var testLoggerManager = new DummyTestLoggerManager(); Assert.ThrowsException( - () => testLoggerManager.InitializeLoggerByUri(null, null)); + () => testLoggerManager.InitializeLoggerByUri(null!, null)); } [TestMethod] @@ -348,7 +348,7 @@ public void LoggerInitialzeShouldCollectLoggersForTelemetry() mockRequestData.Setup(rd => rd.MetricsCollection).Returns(mockMetricsCollection.Object); var testLoggerManager = new DummyTestLoggerManager(mockRequestData.Object); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); // Act. testLoggerManager.Initialize(null); @@ -372,7 +372,7 @@ public void HandleDiscoveryStartShouldInvokeDiscoveryStartHandlerOfLoggers() // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.HandleDiscoveryStart(discoveryStartEventArgs); @@ -396,7 +396,7 @@ public void HandleDiscoveryStartShouldNotInvokeDiscoveryStartHandlerOfLoggersIfD // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.Dispose(); @@ -420,7 +420,7 @@ public void HandleDiscoveredTestsShouldInvokeDiscoveredTestsHandlerOfLoggers() // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.HandleDiscoveredTests(discoveredTestsEventArgs); @@ -441,7 +441,7 @@ public void HandleDiscoveredTestsShouldNotInvokeDiscoveredTestsHandlerOfLoggersI // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.Dispose(); @@ -465,7 +465,7 @@ public void HandleTestRunStartShouldInvokeTestRunStartHandlerOfLoggers() // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.HandleTestRunStart(testRunStartEventArgs); @@ -489,7 +489,7 @@ public void HandleTestRunStartShouldNotInvokeTestRunStartHandlerOfLoggersIfDispo // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.Dispose(); @@ -512,7 +512,7 @@ public void HandleDiscoveryCompleteShouldInvokeDiscoveryCompleteHandlerOfLoggers // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.HandleDiscoveryComplete(discoveryCompleteEventArgs); @@ -535,7 +535,7 @@ public void HandleDiscoveryCompleteShouldNotInvokeDiscoveryCompleteHandlerOfLogg // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.Dispose(); @@ -552,7 +552,7 @@ public void HandleDiscoveryCompleteShouldDisposeLoggerManager() WaitHandle.Reset(); // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); var discoveryCompleteEventArgs = new DiscoveryCompleteEventArgs(2, false); @@ -576,7 +576,7 @@ public void HandleDiscoveryMessageShouldInvokeDiscoveryMessageHandlerOfLoggers() // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.HandleDiscoveryMessage(testRunMessageEventArgs); @@ -600,7 +600,7 @@ public void HandleDiscoveryMessageShouldNotInvokeDiscoveryMessageHandlerOfLogger // setup TestLogger var testLoggerManager = new DummyTestLoggerManager(); - testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new Dictionary()); + testLoggerManager.InitializeLoggerByUri(new Uri(_loggerUri), new()); testLoggerManager.EnableLogging(); testLoggerManager.Dispose(); @@ -1673,12 +1673,14 @@ public static void Reset() internal class DummyTestLoggerManager : TestLoggerManager { - public DummyTestLoggerManager() : base(null, TestSessionMessageLogger.Instance, new InternalTestLoggerEvents(TestSessionMessageLogger.Instance)) + public DummyTestLoggerManager() + : base(null!, TestSessionMessageLogger.Instance, new InternalTestLoggerEvents(TestSessionMessageLogger.Instance)) { } - public DummyTestLoggerManager(IRequestData requestData) : base(requestData, TestSessionMessageLogger.Instance, new InternalTestLoggerEvents(TestSessionMessageLogger.Instance)) + public DummyTestLoggerManager(IRequestData requestData) + : base(requestData, TestSessionMessageLogger.Instance, new InternalTestLoggerEvents(TestSessionMessageLogger.Instance)) { } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestSession/TestSessionPoolTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestSession/TestSessionPoolTests.cs index c6fa7c063a..2bdaa45570 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestSession/TestSessionPoolTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestSession/TestSessionPoolTests.cs @@ -79,7 +79,7 @@ public void TakeProxyShouldSucceedIfMatchingCriteriaAreCorrect() mockProxyTestSessionManager.SetupSequence(tsm => tsm.DequeueProxy(It.IsAny(), It.IsAny())) .Throws(new InvalidOperationException("Test Exception")) - .Returns(new ProxyOperationManager(null, null, null, Framework.DefaultFramework)); + .Returns(new ProxyOperationManager(null, null!, null!, Framework.DefaultFramework)); Assert.IsNotNull(TestSessionPool.Instance); // Take proxy fails because test session is invalid. diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestableImplementations/TestableTestRunCache.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestableImplementations/TestableTestRunCache.cs index afbcd1a122..641e04e281 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestableImplementations/TestableTestRunCache.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/TestableImplementations/TestableTestRunCache.cs @@ -16,6 +16,9 @@ public TestableTestRunCache() TestStartedList = new List(); TestCompletedList = new List(); TestResultList = new List(); + TestResults = null!; + InProgressTests = null!; + TestRunStatistics = null!; } // use the below three to fill in data to the testable cache. @@ -25,13 +28,13 @@ public TestableTestRunCache() public List TestResultList { get; private set; } - public ICollection? InProgressTests { get; set; } + public ICollection InProgressTests { get; set; } // Use the TestResultList instead to fill in data. This is just to avoid confusion. - public ICollection? TestResults { get; set; } + public ICollection TestResults { get; set; } - public TestRunStatistics? TestRunStatistics { get; set; } + public TestRunStatistics TestRunStatistics { get; set; } public long TotalExecutedTests { get; set; } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Utilities/TestSourcesUtilityTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Utilities/TestSourcesUtilityTests.cs index abec7f4a20..5d780889b6 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Utilities/TestSourcesUtilityTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Utilities/TestSourcesUtilityTests.cs @@ -20,14 +20,14 @@ public class TestSourcesUtilityTests [TestMethod] public void GetSourcesShouldAggregateSourcesIfMultiplePresentInAdapterSourceMap() { - var adapterSourceMap = new Dictionary> + var adapterSourceMap = new Dictionary?> { { "adapter1", new List() { "source1.dll", "source2.dll" } }, { "adapter2", new List() { "source1.dll", "source3.dll" } }, { "adapter3", new List() { "source1.dll" } } }; - var sources = TestSourcesUtility.GetSources(adapterSourceMap); + var sources = TestSourcesUtility.GetSources(adapterSourceMap)!; Assert.AreEqual(5, sources.Count()); Assert.IsTrue(sources.Contains("source1.dll")); Assert.IsTrue(sources.Contains("source2.dll")); @@ -51,7 +51,7 @@ public void GetSourcesShouldGetDistinctSourcesFromTestCases() [TestMethod] public void GetDefaultCodeBasePathShouldReturnNullIfAdapterSourceMapIsEmpty() { - var adapterSourceMap = new Dictionary>(); + var adapterSourceMap = new Dictionary?>(); var defaultCodeBase = TestSourcesUtility.GetDefaultCodebasePath(adapterSourceMap); Assert.IsNull(defaultCodeBase); @@ -69,7 +69,7 @@ public void GetDefaultCodeBasePathShouldReturnNullIfTestCaseListIsEmpty() [TestMethod] public void GetDefaultCodeBasePathShouldReturnDefaultDirectoryPathForAdapterSourceMap() { - var adapterSourceMap = new Dictionary> + var adapterSourceMap = new Dictionary?> { { "adapter1", new List() { Path.Combine(Temp, "folder1", "source1.dll"), Path.Combine(Temp, "folder2", "source2.dll") } } }; diff --git a/test/Microsoft.TestPlatform.PerformanceTests/TranslationLayer/TelemetryPerfTestBase.cs b/test/Microsoft.TestPlatform.PerformanceTests/TranslationLayer/TelemetryPerfTestBase.cs index d7fff8cf11..aaae4f9e65 100644 --- a/test/Microsoft.TestPlatform.PerformanceTests/TranslationLayer/TelemetryPerfTestBase.cs +++ b/test/Microsoft.TestPlatform.PerformanceTests/TranslationLayer/TelemetryPerfTestBase.cs @@ -71,7 +71,18 @@ public void PostTelemetry(IDictionary handlerMetrics, PerfAnalyz foreach (var entry in perfAnalyzer.Events) { - metrics.Add(entry.Name, entry.TimeSinceStart); + // TODO: Jajares: What do we want to do in case of duplicated metric key? + // It used to be a metrics.Add() call but it was causing the errors below when running tests in parallel: + // Test method Microsoft.TestPlatform.PerformanceTests.TranslationLayer.DiscoveryPerfTests.DiscoverTests threw exception: + // System.ArgumentException: An item with the same key has already been added. + // Stack Trace: + // ThrowHelper.ThrowArgumentException(ExceptionResource resource) + // Dictionary`2.Insert(TKey key, TValue value, Boolean add) + // TelemetryPerfTestBase.PostTelemetry(IDictionary`2 handlerMetrics, PerfAnalyzer perfAnalyzer, String projectName, String scenario) line 74 + // DiscoveryPerfTests.DiscoverTests(String projectName, Double expectedNumberOfTests) line 49 + // It was both for DiscoveryPerfTests and ExecutionPerfTests. + // I am doing a set call instead but that means we would override previous value. + metrics[entry.Name] = entry.TimeSinceStart; } _client.TrackEvent($"{scenario}{projectName}", properties, metrics); diff --git a/test/datacollector.PlatformTests/CommunicationLayerIntegrationTests.cs b/test/datacollector.PlatformTests/CommunicationLayerIntegrationTests.cs index 83e59b1037..9a5d96472d 100644 --- a/test/datacollector.PlatformTests/CommunicationLayerIntegrationTests.cs +++ b/test/datacollector.PlatformTests/CommunicationLayerIntegrationTests.cs @@ -54,7 +54,7 @@ public void BeforeTestRunStartShouldGetEnviornmentVariables() var result = proxyDataCollectionManager.BeforeTestRunStart(true, true, _mockTestMessageEventHandler.Object); - Assert.AreEqual(1, result.EnvironmentVariables.Count); + Assert.AreEqual(1, result.EnvironmentVariables?.Count); } [TestMethod] @@ -69,7 +69,7 @@ public void AfterTestRunShouldSendGetAttachments() var dataCollectionResult = proxyDataCollectionManager.AfterTestRunEnd(false, _mockTestMessageEventHandler.Object); - Assert.AreEqual("CustomDataCollector", dataCollectionResult.Attachments[0].DisplayName); + Assert.AreEqual("CustomDataCollector", dataCollectionResult.Attachments![0].DisplayName); Assert.AreEqual("my://custom/datacollector", dataCollectionResult.Attachments[0].Uri.ToString()); Assert.IsTrue(dataCollectionResult.Attachments[0].Attachments[0].Uri.ToString().Contains("filename.txt")); } diff --git a/test/vstest.ProgrammerTests/Fakes/FakeTestRuntimeProviderManager.cs b/test/vstest.ProgrammerTests/Fakes/FakeTestRuntimeProviderManager.cs index e19ff8ebba..acf11b261f 100644 --- a/test/vstest.ProgrammerTests/Fakes/FakeTestRuntimeProviderManager.cs +++ b/test/vstest.ProgrammerTests/Fakes/FakeTestRuntimeProviderManager.cs @@ -35,16 +35,16 @@ public void AddTestRuntimeProviders(params FakeTestRuntimeProvider[] runtimeProv } } - public ITestRuntimeProvider GetTestHostManagerByRunConfiguration(string _, List sources) + public ITestRuntimeProvider? GetTestHostManagerByRunConfiguration(string? _, List? sources) { var allMatchingProviders = TestRuntimeProviders .Where(r => r.TestDlls.Select(dll => dll.Path) - .Any(path => sources.Contains(path))) + .Any(path => sources?.Contains(path) == true)) .ToList(); if (allMatchingProviders.Count == 0) { - throw new InvalidOperationException($"There are no FakeTestRuntimeProviders associated with any of the incoming sources, make sure your testhost fixture has at least one dll: {sources.JoinByComma()}"); + throw new InvalidOperationException($"There are no FakeTestRuntimeProviders associated with any of the incoming sources, make sure your testhost fixture has at least one dll: {sources?.JoinByComma()}"); } if (allMatchingProviders.Count > 1)