diff --git a/shared/NullableAttributes.cs b/shared/NullableAttributes.cs index eae553f0ae..ec8978cab4 100644 --- a/shared/NullableAttributes.cs +++ b/shared/NullableAttributes.cs @@ -144,6 +144,8 @@ public MemberNotNullWhenAttribute(bool returnValue, params string[] members) public string[] Members { get; } } +#endif + /// /// Secret attribute that tells the CA1062 validate arguments rule that this method validates the argument is not null. /// @@ -151,5 +153,3 @@ public MemberNotNullWhenAttribute(bool returnValue, params string[] members) internal sealed class ValidatedNotNullAttribute : Attribute { } - -#endif diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IDataAttachment.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IDataAttachment.cs index 1f43822431..6d904dc0ed 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IDataAttachment.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IDataAttachment.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.TestPlatform.Extensions.TrxLogger.ObjectModel; /// diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestAggregation.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestAggregation.cs index ed47cf5559..832cfa408b 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestAggregation.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestAggregation.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Generic; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; internal interface ITestAggregation : ITestElement diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestElement.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestElement.cs index 7f807c4230..05400534c5 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestElement.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestElement.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.TestPlatform.Extensions.TrxLogger.ObjectModel; internal interface ITestElement diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestResult.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestResult.cs index 374fc2e210..7f2acd7fa3 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestResult.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestResult.cs @@ -3,14 +3,12 @@ using System; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; internal interface ITestResult { TestResultId Id { get; } - string ResultType { get; set; } + string? ResultType { get; set; } string StdOut { get; set; } string StdErr { get; set; } string DebugTrace { get; set; } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestResultAggregation.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestResultAggregation.cs index c5220a42d0..6746baf0ce 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestResultAggregation.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/ITestResultAggregation.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; internal interface ITestResultAggregation : ITestResult diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IXmlTestStore.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IXmlTestStore.cs index 7eec124cb8..f4dd43d360 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IXmlTestStore.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IXmlTestStore.cs @@ -3,8 +3,6 @@ using System.Xml; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -18,5 +16,5 @@ internal interface IXmlTestStore /// /// XmlElement element /// XmlTestStoreParameters parameters - void Save(XmlElement element, XmlTestStoreParameters parameters); + void Save(XmlElement element, XmlTestStoreParameters? parameters); } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IXmlTestStoreCustom.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IXmlTestStoreCustom.cs index 3ab4c64025..262ef2ca61 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IXmlTestStoreCustom.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/IXmlTestStoreCustom.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.TestPlatform.Extensions.TrxLogger.XML; /// @@ -18,5 +16,5 @@ internal interface IXmlTestStoreCustom /// /// Gets the xml namespace to use when creating the element /// - string NamespaceUri { get; } + string? NamespaceUri { get; } } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/XmlTestStoreParameters.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/XmlTestStoreParameters.cs index adea39488d..7c80a209dc 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/XmlTestStoreParameters.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Interfaces/XmlTestStoreParameters.cs @@ -3,16 +3,14 @@ using System.Collections.Generic; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// -/// Optional parameters to the persistence process. A class implementing IPersistable can +/// Optional parameters to the persistence process. A class implementing IPersistable can /// use the parameter values to alter its load/save behavior. /// /// -/// Example: a class has a summary and details fields. Details are large, so they're only +/// Example: a class has a summary and details fields. Details are large, so they're only /// saved when 'MyClass.SaveDetails' parameter is set to 'true'. /// internal sealed class XmlTestStoreParameters : Dictionary diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft - Backup.TestPlatform.Extensions.TrxLogger.csproj b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft - Backup.TestPlatform.Extensions.TrxLogger.csproj new file mode 100644 index 0000000000..dda735f4ae --- /dev/null +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft - Backup.TestPlatform.Extensions.TrxLogger.csproj @@ -0,0 +1,75 @@ + + + + ..\..\ + + + + Microsoft.VisualStudio.TestPlatform.Extensions.Trx.TestLogger + netstandard2.0;net451 + net6.0 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + NullableHelpers.tt + + + True + True + TrxResource.resx + + + + + ResXFileCodeGenerator + TrxResource.Designer.cs + + + + Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger + + + + + + + + + + + + NullableHelpers.cs + TextTemplatingFileGenerator + + + + + + + diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft.TestPlatform.Extensions.TrxLogger.csproj b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft.TestPlatform.Extensions.TrxLogger.csproj index 03fd2d54b8..22566329ba 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft.TestPlatform.Extensions.TrxLogger.csproj +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Microsoft.TestPlatform.Extensions.TrxLogger.csproj @@ -6,7 +6,7 @@ Microsoft.VisualStudio.TestPlatform.Extensions.Trx.TestLogger - netstandard2.0;net451 + net6.0;netstandard2.0;net451 net6.0 false @@ -21,6 +21,7 @@ + @@ -33,6 +34,11 @@ + + True + True + NullableHelpers.tt + True True @@ -56,5 +62,14 @@ + + + TextTemplatingFileGenerator + NullableHelpers.cs + + + + + diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/NullableHelpers.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/NullableHelpers.cs new file mode 100644 index 0000000000..6f719c4f40 --- /dev/null +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/NullableHelpers.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// This code is auto-generated. Changes to this file will be lost! +// This T4 file is copied in various projects because inclusion as link or through shared project +// doesn't allow to generate the C# file locally. If some modification is required, please update +// all instances. +// + +#nullable enable + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; + +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); +} + +[SuppressMessage("ApiDesign", "RS0030:Do not used banned APIs", Justification = "Replacement API to allow nullable hints for compiler")] +internal static class TPDebug +{ + /// + [Conditional("DEBUG")] + public static void Assert([DoesNotReturnIf(false)] bool b) + => TPDebug.Assert(b); + + /// + [Conditional("DEBUG")] + public static void Assert([DoesNotReturnIf(false)] bool b, string message) + => TPDebug.Assert(b, message); +} diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/NullableHelpers.tt b/src/Microsoft.TestPlatform.Extensions.TrxLogger/NullableHelpers.tt new file mode 100644 index 0000000000..cf74926c25 --- /dev/null +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/NullableHelpers.tt @@ -0,0 +1,45 @@ +<#@ template debug="true" hostspecific="true" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// This code is auto-generated. Changes to this file will be lost! +// This T4 file is copied in various projects because inclusion as link or through shared project +// doesn't allow to generate the C# file locally. If some modification is required, please update +// all instances. +// + +#nullable enable + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace <#= System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint") #>; + +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); +} + +[SuppressMessage("ApiDesign", "RS0030:Do not used banned APIs", Justification = "Replacement API to allow nullable hints for compiler")] +internal static class TPDebug +{ + /// + [Conditional("DEBUG")] + public static void Assert([DoesNotReturnIf(false)] bool b) + => TPDebug.Assert(b); + + /// + [Conditional("DEBUG")] + public static void Assert([DoesNotReturnIf(false)] bool b, string message) + => TPDebug.Assert(b, message); +} diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/CollectorDataEntry.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/CollectorDataEntry.cs index 0a6730e279..8093315689 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/CollectorDataEntry.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/CollectorDataEntry.cs @@ -3,16 +3,13 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Xml; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; - using Microsoft.TestPlatform.Extensions.TrxLogger.XML; +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; using Microsoft.VisualStudio.TestPlatform.ObjectModel; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -26,32 +23,32 @@ internal class CollectorDataEntry : IXmlTestStore /// List of data attachments. These attachments can be things such as files that the /// collector wants to make available to the publishers. /// - private readonly List _attachments; + private readonly List _attachments = new(); /// /// Name of the agent from which we received the data /// - private string _agentName; + private readonly string _agentName; /// /// Display name of the agent from which we received the data /// - private string _agentDisplayName; + private readonly string _agentDisplayName; /// /// Flag indicating whether this data is coming from a remote (not hosted) agent /// - private bool _isFromRemoteAgent; + private readonly bool _isFromRemoteAgent; /// /// URI of the collector. /// - private Uri _uri; + private readonly Uri _uri; /// /// Name of the collector that should be displayed to the user. /// - private string _collectorDisplayName; + private readonly string _collectorDisplayName; /// /// Used by the aggregator to put collector Uri, agentName, string agentDisplayName, whether it's remote data, and @@ -75,10 +72,28 @@ internal class CollectorDataEntry : IXmlTestStore /// /// The attachments. /// - public CollectorDataEntry(Uri uri, string collectorDisplayName, string agentName, string agentDisplayName, bool isFromRemoteAgent, IList attachments) - : this() + public CollectorDataEntry(Uri uri, string collectorDisplayName, string agentName, string agentDisplayName, bool isFromRemoteAgent, IList? attachments) { - Initialize(uri, collectorDisplayName, agentName, agentDisplayName, isFromRemoteAgent, attachments); + EqtAssert.ParameterNotNull(uri, nameof(uri)); + EqtAssert.StringNotNullOrEmpty(collectorDisplayName, nameof(collectorDisplayName)); + EqtAssert.StringNotNullOrEmpty(agentName, nameof(agentName)); + EqtAssert.StringNotNullOrEmpty(agentDisplayName, nameof(agentDisplayName)); + + if (null != attachments) + { + // Copy the attachments + foreach (IDataAttachment attachment in attachments) + { + AddAttachment(attachment); + } + } + + // Note that the data can be null. + _uri = uri; + _collectorDisplayName = collectorDisplayName; + _agentName = agentName.Trim(); + _agentDisplayName = agentDisplayName.Trim(); + _isFromRemoteAgent = isFromRemoteAgent; } /// @@ -89,39 +104,10 @@ public CollectorDataEntry(Uri uri, string collectorDisplayName, string agentName /// internal CollectorDataEntry() { - _attachments = new List(); - } - - /// - /// Copies the specified collector data entry, making the paths in the data attachments absolute or relative, with - /// respect to the results directory - /// - /// The instance to copy from - /// The results directory to use to make paths in the data attachments relative or absolute - /// True to use absolute paths in this instance, false to use relative paths - private CollectorDataEntry(CollectorDataEntry other, string resultsDirectory, bool useAbsolutePaths) - { - Debug.Assert(other != null, "'other' is null"); - Debug.Assert(other._attachments != null, "'other.m_attachments' is null"); - Debug.Assert(!string.IsNullOrEmpty(resultsDirectory), "'resultsDirectory' is null or empty"); - - _attachments = new List(other._attachments.Count); - Initialize(other._uri, other._collectorDisplayName, other._agentName, other._agentDisplayName, other._isFromRemoteAgent, null); - - // Clone the attachments - foreach (IDataAttachment attachment in other._attachments) - { - Debug.Assert(attachment != null, "'attachment' is null"); - - if (attachment is UriDataAttachment uriDataAttachment) - { - _attachments.Add(uriDataAttachment.Clone(resultsDirectory, useAbsolutePaths)); - } - else - { - _attachments.Add(attachment); - } - } + _agentName = null!; + _agentDisplayName = null!; + _uri = null!; + _collectorDisplayName = null!; } /// @@ -143,7 +129,7 @@ public IList Attachments /// /// The XML element to save to /// Parameters to customize the save behavior - public void Save(XmlElement element, XmlTestStoreParameters parameters) + public void Save(XmlElement element, XmlTestStoreParameters? parameters) { EqtAssert.ParameterNotNull(element, nameof(element)); @@ -185,34 +171,26 @@ internal void AddAttachment(IDataAttachment attachment) /// A clone of the instance containing cloned attachments with file paths made absolute or relative internal CollectorDataEntry Clone(string resultsDirectory, bool useAbsolutePaths) { - Debug.Assert(!string.IsNullOrEmpty(resultsDirectory), "'resultsDirectory' is null or empty"); - Debug.Assert(resultsDirectory == resultsDirectory.Trim(), "'resultsDirectory' contains whitespace at the ends"); + TPDebug.Assert(!resultsDirectory.IsNullOrEmpty(), "'resultsDirectory' is null or empty"); + TPDebug.Assert(resultsDirectory == resultsDirectory.Trim(), "'resultsDirectory' contains whitespace at the ends"); - return new CollectorDataEntry(this, resultsDirectory, useAbsolutePaths); - } - - private void Initialize(Uri uri, string collectorDisplayName, string agentName, string agentDisplayName, bool isFromRemoteAgent, IEnumerable attachments) - { - EqtAssert.ParameterNotNull(uri, nameof(uri)); - EqtAssert.StringNotNullOrEmpty(collectorDisplayName, nameof(collectorDisplayName)); - EqtAssert.StringNotNullOrEmpty(agentName, nameof(agentName)); - EqtAssert.StringNotNullOrEmpty(agentDisplayName, nameof(agentDisplayName)); + var collector = new CollectorDataEntry(_uri, _collectorDisplayName, _agentName, _agentDisplayName, _isFromRemoteAgent, null); - if (null != attachments) + // Clone the attachments + foreach (IDataAttachment attachment in _attachments) { - // Copy the attachments - foreach (IDataAttachment attachment in attachments) + TPDebug.Assert(attachment is not null, "'attachment' is null"); + + if (attachment is UriDataAttachment uriDataAttachment) { - AddAttachment(attachment); + collector._attachments.Add(uriDataAttachment.Clone(resultsDirectory, useAbsolutePaths)); + } + else + { + collector._attachments.Add(attachment); } } - // Note that the data can be null. - _uri = uri; - _collectorDisplayName = collectorDisplayName; - _agentName = agentName.Trim(); - _agentDisplayName = agentDisplayName.Trim(); - _isFromRemoteAgent = isFromRemoteAgent; + return collector; } - } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/OrderedTestElement.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/OrderedTestElement.cs index 2a040e2ca1..5046a0c619 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/OrderedTestElement.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/OrderedTestElement.cs @@ -4,11 +4,8 @@ using System; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; - using Microsoft.TestPlatform.Extensions.TrxLogger.XML; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -23,7 +20,7 @@ string IXmlTestStoreCustom.ElementName get { return Constants.OrderedTestElementName; } } - string IXmlTestStoreCustom.NamespaceUri + string? IXmlTestStoreCustom.NamespaceUri { get { return null; } } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/RunInfo.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/RunInfo.cs index fd51841843..4c245f3e2e 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/RunInfo.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/RunInfo.cs @@ -2,12 +2,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Diagnostics; using System.Xml; using Microsoft.TestPlatform.Extensions.TrxLogger.XML; - -#nullable disable +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; @@ -19,7 +17,7 @@ internal sealed class RunInfo : IXmlTestStore [StoreXmlSimpleField("Text", "")] private readonly string _text; - private readonly Exception _exception; + private readonly Exception? _exception; [StoreXmlSimpleField("@computerName", "")] private readonly string _computer; @@ -45,9 +43,9 @@ internal sealed class RunInfo : IXmlTestStore /// /// The outcome. /// - public RunInfo(string textMessage, Exception ex, string computer, TestOutcome outcome) + public RunInfo(string textMessage, Exception? ex, string computer, TestOutcome outcome) { - Debug.Assert(computer != null, "computer is null"); + TPDebug.Assert(computer != null, "computer is null"); _text = textMessage; _exception = ex; @@ -56,7 +54,6 @@ public RunInfo(string textMessage, Exception ex, string computer, TestOutcome ou _timestamp = DateTime.UtcNow; } - #region IXmlTestStore Members /// @@ -68,7 +65,7 @@ public RunInfo(string textMessage, Exception ex, string computer, TestOutcome ou /// /// The parameters. /// - public void Save(XmlElement element, XmlTestStoreParameters parameters) + public void Save(XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence helper = new(); helper.SaveSingleFields(element, this, parameters); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestCategoryItems.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestCategoryItems.cs index 552ef6c09b..88a699e409 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestCategoryItems.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestCategoryItems.cs @@ -2,16 +2,14 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Diagnostics; using System.Text; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; - using Microsoft.TestPlatform.Extensions.TrxLogger.XML; - -#nullable disable +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; + #region TestCategoryItem /// /// Stores a string which categorizes the Test @@ -25,7 +23,7 @@ internal sealed class TestCategoryItem : IXmlTestStore /// Create a new item with the category set /// /// The category. - public TestCategoryItem(string category) + public TestCategoryItem(string? category) { // Treat null as empty. if (category == null) @@ -48,7 +46,7 @@ public string TestCategory } } - private string StripIllegalChars(string category) + private static string StripIllegalChars(string category) { string ret = category.Trim(); ret = ret.Replace("&", string.Empty); @@ -63,13 +61,14 @@ private string StripIllegalChars(string category) /// /// Value being compared to. /// True if the values are the same and false otherwise. - public override bool Equals(object other) + public override bool Equals(object? other) { if (other is not TestCategoryItem otherItem) { return false; } - Debug.Assert(_category != null, "category is null"); + + TPDebug.Assert(_category != null, "category is null"); return string.Equals(_category, otherItem._category, StringComparison.OrdinalIgnoreCase); } @@ -79,7 +78,7 @@ public override bool Equals(object other) /// Hashcode of the category. public override int GetHashCode() { - Debug.Assert(_category != null, "category is null"); + TPDebug.Assert(_category != null, "category is null"); return _category.ToUpperInvariant().GetHashCode(); } @@ -89,7 +88,7 @@ public override int GetHashCode() /// The category. public override string ToString() { - Debug.Assert(_category != null, "category is null"); + TPDebug.Assert(_category != null, "category is null"); return _category; } @@ -100,7 +99,7 @@ public override string ToString() /// /// XmlElement element /// XmlTestStoreParameters parameters - public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { new XmlPersistence().SaveSingleFields(element, this, parameters); } @@ -153,7 +152,7 @@ public override void Add(TestCategoryItem item) EqtAssert.ParameterNotNull(item, nameof(item)); // Don't add empty items. - if (!string.IsNullOrEmpty(item.TestCategory)) + if (!item.TestCategory.IsNullOrEmpty()) { base.Add(item); } @@ -202,7 +201,7 @@ public string[] ToArray() /// /// other collection /// true if the collections contain the same items - public override bool Equals(object obj) + public override bool Equals(object? obj) { bool result = false; diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElement.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElement.cs index e7ef822442..9e48e7aae4 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElement.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElement.cs @@ -2,17 +2,14 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Diagnostics; using System.Globalization; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; - using Microsoft.TestPlatform.Extensions.TrxLogger.XML; +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -40,10 +37,18 @@ internal abstract class TestElement : ITestElement, IXmlTestStore public TestElement(Guid id, string name, string adapter) { - Debug.Assert(!string.IsNullOrEmpty(name), "name is null"); - Debug.Assert(!string.IsNullOrEmpty(adapter), "adapter is null"); + TPDebug.Assert(!name.IsNullOrEmpty(), "name is null"); + TPDebug.Assert(!adapter.IsNullOrEmpty(), "adapter is null"); - Initialize(); + _owner = string.Empty; + _priority = DefaultPriority; + _storage = string.Empty; + _executionId = TestExecId.Empty; + _parentExecutionId = TestExecId.Empty; + _testCategories = new TestCategoryItemCollection(); + _workItems = new WorkItemCollection(); + _isRunnable = true; + _catId = TestListCategoryId.Uncategorized; _id = new TestId(id); _name = name; @@ -215,7 +220,7 @@ public override string ToString() /// /// The . /// - public override bool Equals(object other) + public override bool Equals(object? other) { return other is TestElement otherTest && _id.Equals(otherTest._id); } @@ -231,7 +236,7 @@ public override int GetHashCode() return _id.GetHashCode(); } - public virtual void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public virtual void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence h = new(); @@ -252,19 +257,4 @@ public virtual void Save(System.Xml.XmlElement element, XmlTestStoreParameters p testIdParameters[TestId.IdLocationKey] = "@id"; h.SaveObject(_id, element, testIdParameters); } - - private void Initialize() - { - _id = TestId.Empty; - _name = string.Empty; - _owner = string.Empty; - _priority = DefaultPriority; - _storage = string.Empty; - _executionId = TestExecId.Empty; - _parentExecutionId = TestExecId.Empty; - _testCategories = new TestCategoryItemCollection(); - _workItems = new WorkItemCollection(); - _isRunnable = true; - _catId = TestListCategoryId.Uncategorized; - } } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElementAggregation.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElementAggregation.cs index 65100a07e1..7ee95be907 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElementAggregation.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestElementAggregation.cs @@ -6,8 +6,6 @@ using Microsoft.TestPlatform.Extensions.TrxLogger.XML; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -27,7 +25,7 @@ public Dictionary TestLinks get { return _testLinks; } } - public override void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public override void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { base.Save(element, parameters); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestEntry.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestEntry.cs index 67fd3ec7ae..73c4c97c87 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestEntry.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestEntry.cs @@ -3,11 +3,9 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using Microsoft.TestPlatform.Extensions.TrxLogger.XML; - -#nullable disable +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; @@ -18,7 +16,7 @@ internal sealed class TestEntry : IXmlTestStore { private readonly TestId _testId; private readonly TestListCategoryId _categoryId; - private List _testEntries; + private List? _testEntries; /// /// Constructor. @@ -65,7 +63,7 @@ public List TestEntries /// /// The . /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is not TestEntry e) { @@ -77,8 +75,8 @@ public override bool Equals(object obj) return false; } - Debug.Assert(Equals(_testId, e._testId)); - Debug.Assert(Equals(_categoryId, e._categoryId)); + TPDebug.Assert(Equals(_testId, e._testId)); + TPDebug.Assert(Equals(_categoryId, e._categoryId)); return true; } @@ -105,7 +103,7 @@ public override int GetHashCode() /// /// The parameters. /// - public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence helper = new(); helper.SaveSingleFields(element, this, parameters); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestExecId.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestExecId.cs index b08143a6c3..d5aa97ef60 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestExecId.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestExecId.cs @@ -4,8 +4,6 @@ using System; using System.Globalization; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -52,7 +50,7 @@ public TestExecId(Guid id) /// /// The . /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is TestExecId id && Id.Equals(id.Id); } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestId.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestId.cs index b7019bbcbd..92a4680d92 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestId.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestId.cs @@ -2,15 +2,14 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Diagnostics; using System.Globalization; using System.Xml; using Microsoft.TestPlatform.Extensions.TrxLogger.XML; - -#nullable disable +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; + #region TestId /// /// Class that uniquely identifies a test. @@ -62,9 +61,9 @@ public TestId(Guid id) /// /// The XML element to save to /// Parameters to customize the save behavior - void IXmlTestStore.Save(XmlElement element, XmlTestStoreParameters parameters) + void IXmlTestStore.Save(XmlElement element, XmlTestStoreParameters? parameters) { - Debug.Assert(element != null, "element is null"); + TPDebug.Assert(element != null, "element is null"); GetIdLocation(parameters, out string idLocation); @@ -81,7 +80,7 @@ void IXmlTestStore.Save(XmlElement element, XmlTestStoreParameters parameters) /// /// The parameters specifying the locations /// The test ID location - private void GetIdLocation(XmlTestStoreParameters parameters, out string idLocation) + private static void GetIdLocation(XmlTestStoreParameters? parameters, out string idLocation) { // Initialize to the default ID location idLocation = DefaultIdLocation; @@ -89,7 +88,7 @@ private void GetIdLocation(XmlTestStoreParameters parameters, out string idLocat // If any parameters are specified, see if we need to override the defaults if (parameters != null) { - if (parameters.TryGetValue(IdLocationKey, out object idLocationObj)) + if (parameters.TryGetValue(IdLocationKey, out object? idLocationObj)) { idLocation = idLocationObj as string ?? idLocation; } @@ -107,7 +106,7 @@ private void GetIdLocation(XmlTestStoreParameters parameters, out string idLocat /// /// The other test ID to compare with /// True if the test IDs are equal in value, false otherwise - public bool Equals(TestId other) + public bool Equals(TestId? other) { // Check reference equality first, as it is faster than comparing value equality when the references are equal return ReferenceEquals(this, other) || ValueEquals(other); @@ -118,7 +117,7 @@ public bool Equals(TestId other) /// /// The other test ID to compare with /// True if the test IDs are equal in value, false otherwise - private bool ValueEquals(TestId other) + private bool ValueEquals(TestId? other) { // Avoid calling of "!= null", as the != operator has been overloaded. return other is not null && Id == other.Id; @@ -133,7 +132,7 @@ private bool ValueEquals(TestId other) /// /// The other test ID to compare with /// True if the test IDs are equal in value, false otherwise - public override bool Equals(object other) + public override bool Equals(object? other) { return Equals(other as TestId); } @@ -157,7 +156,7 @@ public override int GetHashCode() /// The test ID on the left of the operator /// The test ID on the right of the operator /// True if the test IDs are equal in value, false otherwise - public static bool operator ==(TestId left, TestId right) + public static bool operator ==(TestId? left, TestId? right) { return ReferenceEquals(left, right) || @@ -170,7 +169,7 @@ public override int GetHashCode() /// The test ID on the left of the operator /// The test ID on the right of the operator /// True if the test IDs are unequal in value, false otherwise - public static bool operator !=(TestId left, TestId right) + public static bool operator !=(TestId? left, TestId? right) { return !(left == right); } @@ -191,7 +190,7 @@ public override int GetHashCode() /// 0 if this instance is equal in value to the other test ID, < 0 if this instance is lesser than the other test ID, /// or > 0 if this instance is greater than the other test ID /// - public int CompareTo(TestId other) + public int CompareTo(TestId? other) { return other == null ? throw new ArgumentNullException(nameof(other)) : Id.CompareTo(other.Id); } @@ -208,7 +207,7 @@ public int CompareTo(TestId other) /// 0 if this instance is equal in value to the other test ID, < 0 if this instance is less than the other test ID, /// or > 0 if this instance is greater than the other test ID /// - public int CompareTo(object other) + public int CompareTo(object? other) { return CompareTo(other as TestId); } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestLink.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestLink.cs index 022d3e7655..8cd4ff284c 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestLink.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestLink.cs @@ -5,11 +5,8 @@ using System.Globalization; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; - using Microsoft.TestPlatform.Extensions.TrxLogger.XML; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -50,7 +47,7 @@ public TestLink(Guid id, string name, string storage) /// /// Whether this Link is equal to other Link. Compares by Id. /// - public override bool Equals(object other) + public override bool Equals(object? other) { return other is TestLink link && Id.Equals(link.Id); } @@ -89,7 +86,7 @@ public override string ToString() Storage ?? "(null)"); } - public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence h = new(); h.SaveGuid(element, "@id", Id); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestListCategory.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestListCategory.cs index da80a83f9d..5cff506ae2 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestListCategory.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestListCategory.cs @@ -1,16 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Diagnostics; - using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; - using Microsoft.TestPlatform.Extensions.TrxLogger.XML; +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -18,9 +14,8 @@ namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// internal class TestListCategory : IXmlTestStore { - private static TestListCategory s_uncategorizedResults; - - private static TestListCategory s_allResults; + private static TestListCategory? s_uncategorizedResults; + private static TestListCategory? s_allResults; private static readonly object ReservedCategoryLock = new(); [StoreXmlSimpleField("@name", DefaultValue = "")] @@ -141,14 +136,14 @@ public TestListCategoryId ParentCategoryId /// /// The . /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is not TestListCategory cat) { return false; } - Debug.Assert(Id != null, "id is null"); + TPDebug.Assert(Id != null, "id is null"); return Id.Equals(cat.Id); } @@ -175,7 +170,7 @@ public override int GetHashCode() /// /// The parameter /// - public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence h = new(); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestListCategoryId.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestListCategoryId.cs index 50e68770a4..c88bfe3cbe 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestListCategoryId.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestListCategoryId.cs @@ -4,8 +4,6 @@ using System; using System.Globalization; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -73,7 +71,7 @@ public static TestListCategoryId Empty /// /// The . /// - public override bool Equals(object other) + public override bool Equals(object? other) { return other is TestListCategoryId testListCategoryId && Id.Equals(testListCategoryId.Id); } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestMethod.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestMethod.cs index 80753899aa..01e74c1331 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestMethod.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestMethod.cs @@ -1,12 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Diagnostics; using System.Xml; using Microsoft.TestPlatform.Extensions.TrxLogger.XML; - -#nullable disable +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; @@ -17,8 +15,8 @@ internal sealed class TestMethod : IXmlTestStore { public TestMethod(string name, string className) { - Debug.Assert(!string.IsNullOrEmpty(name), "name is null"); - Debug.Assert(!string.IsNullOrEmpty(className), "className is null"); + TPDebug.Assert(!name.IsNullOrEmpty(), "name is null"); + TPDebug.Assert(!className.IsNullOrEmpty(), "className is null"); Name = name; ClassName = className; } @@ -49,7 +47,7 @@ public TestMethod(string name, string className) /// /// The . /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is TestMethod otherTestMethod && Name == otherTestMethod.Name && ClassName == otherTestMethod.ClassName && IsValid == otherTestMethod.IsValid; @@ -79,7 +77,7 @@ public override int GetHashCode() /// /// The parameter /// - public void Save(XmlElement element, XmlTestStoreParameters parameters) + public void Save(XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence helper = new(); helper.SaveSimpleField(element, "@className", ClassName, string.Empty); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestOutcome.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestOutcome.cs index 8bd9cd0b63..b89a457e5b 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestOutcome.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestOutcome.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.TestPlatform.Extensions.TrxLogger.ObjectModel; /// diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestResult.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestResult.cs index 72b63fb317..a1e15e6346 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestResult.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestResult.cs @@ -5,16 +5,16 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; using Microsoft.TestPlatform.Extensions.TrxLogger.XML; +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -74,7 +74,7 @@ public TestResultId(Guid runId, Guid executionId, Guid parentExecutionId, Guid t /// /// The . /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is TestResultId tmpId && _runId.Equals(tmpId._runId) && ExecutionId.Equals((object)tmpId.ExecutionId); } @@ -113,7 +113,7 @@ public override string ToString() /// /// The parameter /// - public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence helper = new(); @@ -134,16 +134,16 @@ public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameter internal sealed class TestResultErrorInfo : IXmlTestStore { [StoreXmlSimpleField("Message", "")] - private string _message; + private string? _message; [StoreXmlSimpleField("StackTrace", "")] - private string _stackTrace; + private string? _stackTrace; /// /// Gets or sets the message. /// - public string Message + public string? Message { get { return _message; } set { _message = value; } @@ -152,7 +152,7 @@ public string Message /// /// Gets or sets the stack trace. /// - public string StackTrace + public string? StackTrace { get { return _stackTrace; } set { _stackTrace = value; } @@ -169,7 +169,7 @@ public string StackTrace /// /// The parameter /// - public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence.SaveUsingReflection(element, this, typeof(TestResultErrorInfo), parameters); } @@ -183,13 +183,13 @@ public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameter internal class TestResult : ITestResult, IXmlTestStore { private readonly string _resultName; - private string _stdOut; - private string _stdErr; - private string _debugTrace; + private string? _stdOut; + private string? _stdErr; + private string? _debugTrace; private TimeSpan _duration; private readonly TestType _testType; - private TestRun _testRun; - private TestResultErrorInfo _errorInfo; + private TestRun? _testRun; + private TestResultErrorInfo? _errorInfo; private readonly TestListCategoryId _categoryId; private ArrayList _textMessages; private readonly TrxFileHelper _trxFileHelper; @@ -197,7 +197,7 @@ internal class TestResult : ITestResult, IXmlTestStore /// /// Paths to test result files, relative to the test results folder, sorted in increasing order /// - private readonly SortedList _resultFiles = new(StringComparer.OrdinalIgnoreCase); + private readonly SortedList _resultFiles = new(StringComparer.OrdinalIgnoreCase); /// /// Information provided by data collectors for the test case @@ -231,11 +231,12 @@ public TestResult( TestListCategoryId testCategoryId, TrxFileHelper trxFileHelper) { - Debug.Assert(computerName != null, "computername is null"); - Debug.Assert(!Guid.Empty.Equals(executionId), "ExecutionId is empty"); - Debug.Assert(!Guid.Empty.Equals(testId), "TestId is empty"); + TPDebug.Assert(computerName != null, "computername is null"); + TPDebug.Assert(!Guid.Empty.Equals(executionId), "ExecutionId is empty"); + TPDebug.Assert(!Guid.Empty.Equals(testId), "TestId is empty"); - Initialize(); + _textMessages = new ArrayList(); + DataRowInfo = -1; Id = new TestResultId(runId, executionId, parentExecutionId, testId); _resultName = resultName; @@ -329,7 +330,8 @@ public string ErrorStackTrace /// Additional information messages from TestTextResultMessage, e.g. generated by TestOutcome.WriteLine. /// Avoid using this property in the following way: for (int i=0; i<prop.Length; i++) { ... prop[i] ...} /// - public string[] TextMessages + [NotNull] + public string[]? TextMessages { get { return (string[])_textMessages.ToArray(typeof(string)); } @@ -399,24 +401,24 @@ public string TestResultsDirectory /// /// Gets or sets the result type. /// - public string ResultType { get; set; } + public string? ResultType { get; set; } #region Overrides - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is not TestResult trm) { return false; } - Debug.Assert(Id != null, "id is null"); - Debug.Assert(trm.Id != null, "test result message id is null"); + TPDebug.Assert(Id != null, "id is null"); + TPDebug.Assert(trm.Id != null, "test result message id is null"); return Id.Equals(trm.Id); } public override int GetHashCode() { - Debug.Assert(Id != null, "id is null"); + TPDebug.Assert(Id != null, "id is null"); return Id.GetHashCode(); } @@ -438,7 +440,7 @@ public void AddTextMessage(string text) /// The test run the test was executed in internal virtual void SetTestRun(TestRun testRun) { - Debug.Assert(testRun != null, "'testRun' is null"); + TPDebug.Assert(testRun != null, "'testRun' is null"); _testRun = testRun; } @@ -448,13 +450,13 @@ internal virtual void SetTestRun(TestRun testRun) /// Paths to the result files internal void AddResultFiles(IEnumerable resultFileList) { - Debug.Assert(resultFileList != null, "'resultFileList' is null"); + TPDebug.Assert(resultFileList != null, "'resultFileList' is null"); string testResultsDirectory = TestResultsDirectory; foreach (string resultFile in resultFileList) { - Debug.Assert(!string.IsNullOrEmpty(resultFile), "'resultFile' is null or empty"); - Debug.Assert(resultFile.Trim() == resultFile, "'resultFile' has whitespace at the ends"); + TPDebug.Assert(!string.IsNullOrEmpty(resultFile), "'resultFile' is null or empty"); + TPDebug.Assert(resultFile.Trim() == resultFile, "'resultFile' has whitespace at the ends"); _resultFiles[_trxFileHelper.MakePathRelative(resultFile, testResultsDirectory)] = null; } @@ -466,13 +468,13 @@ internal void AddResultFiles(IEnumerable resultFileList) /// The collector data entry to add internal void AddCollectorDataEntries(IEnumerable collectorDataEntryList) { - Debug.Assert(collectorDataEntryList != null, "'collectorDataEntryList' is null"); + TPDebug.Assert(collectorDataEntryList != null, "'collectorDataEntryList' is null"); string testResultsDirectory = TestResultsDirectory; foreach (CollectorDataEntry collectorDataEntry in collectorDataEntryList) { - Debug.Assert(collectorDataEntry != null, "'collectorDataEntry' is null"); - Debug.Assert(!_collectorDataEntries.Contains(collectorDataEntry), "The collector data entry already exists in the collection"); + TPDebug.Assert(collectorDataEntry != null, "'collectorDataEntry' is null"); + TPDebug.Assert(!_collectorDataEntries.Contains(collectorDataEntry), "The collector data entry already exists in the collection"); _collectorDataEntries.Add(collectorDataEntry.Clone(testResultsDirectory, false)); } @@ -490,7 +492,7 @@ internal void AddCollectorDataEntries(IEnumerable collectorD /// /// The parameter /// - public virtual void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public virtual void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence helper = new(); @@ -527,10 +529,4 @@ public virtual void Save(System.Xml.XmlElement element, XmlTestStoreParameters p } #endregion - - private void Initialize() - { - _textMessages = new ArrayList(); - DataRowInfo = -1; - } } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestResultAggregation.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestResultAggregation.cs index e0e76859a7..adb6c8a9c6 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestResultAggregation.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestResultAggregation.cs @@ -8,8 +8,6 @@ using Microsoft.TestPlatform.Extensions.TrxLogger.XML; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -17,7 +15,7 @@ namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// internal class TestResultAggregation : TestResult, ITestResultAggregation { - protected List _innerResults; + protected List? _innerResults; public TestResultAggregation( Guid runId, @@ -29,7 +27,8 @@ public TestResultAggregation( TestOutcome outcome, TestType testType, TestListCategoryId testCategoryId, - TrxFileHelper trxFileHelper) : base(runId, testId, executionId, parentExecutionId, resultName, computerName, outcome, testType, testCategoryId, trxFileHelper) { } + TrxFileHelper trxFileHelper) + : base(runId, testId, executionId, parentExecutionId, resultName, computerName, outcome, testType, testCategoryId, trxFileHelper) { } /// /// Gets the inner results. @@ -46,7 +45,7 @@ public List InnerResults } } - public override void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public override void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { base.Save(element, parameters); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRun.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRun.cs index 81dd3395b5..b714b2a5b3 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRun.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRun.cs @@ -8,13 +8,10 @@ using System.Security.Principal; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; - using Microsoft.TestPlatform.Extensions.TrxLogger.XML; using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -39,15 +36,15 @@ internal sealed class TestRun private string _name; [StoreXmlSimpleField("@runUser", "")] - private string _runUser; + private readonly string _runUser; - private TestRunConfiguration _runConfig; + private TestRunConfiguration? _runConfig; [StoreXmlSimpleField("Times/@creation")] - private DateTime _created; + private readonly DateTime _created; [StoreXmlSimpleField("Times/@queuing")] - private DateTime _queued; + private readonly DateTime _queued; [StoreXmlSimpleField("Times/@start")] private DateTime _started; @@ -63,7 +60,23 @@ internal sealed class TestRun /// internal TestRun(Guid runId) { - Initialize(); + _id = Guid.NewGuid(); + _name = string.Format(CultureInfo.CurrentCulture, TrxLoggerResources.Common_TestRunName, Environment.GetEnvironmentVariable("UserName"), Environment.MachineName, FormatDateTimeForRunName(DateTime.Now)); + + // Fix for issue (https://github.com/Microsoft/vstest/issues/213). Since there is no way to find current user in linux machine. + // We are catching PlatformNotSupportedException for non windows machine. + try + { + _runUser = WindowsIdentity.GetCurrent().Name; + } + catch (PlatformNotSupportedException) + { + _runUser = string.Empty; + } + _created = DateTime.UtcNow; + _queued = DateTime.UtcNow; + _started = DateTime.UtcNow; + _finished = DateTime.UtcNow; EqtAssert.IsTrue(!Guid.Empty.Equals(runId), "Can't use Guid.Empty for run ID."); _id = runId; @@ -72,7 +85,7 @@ internal TestRun(Guid runId) /// /// Gets or sets the run configuration. /// - internal TestRunConfiguration RunConfiguration + internal TestRunConfiguration? RunConfiguration { get { @@ -181,25 +194,4 @@ private static string FormatDateTimeForRunName(DateTime timeStamp) // This is both for directory names and for Data Warehouse. return timeStamp.ToString("yyyy-MM-dd HH:mm:ss", DateTimeFormatInfo.InvariantInfo); } - - private void Initialize() - { - _id = Guid.NewGuid(); - _name = string.Format(CultureInfo.CurrentCulture, TrxLoggerResources.Common_TestRunName, Environment.GetEnvironmentVariable("UserName"), Environment.MachineName, FormatDateTimeForRunName(DateTime.Now)); - - // Fix for issue (https://github.com/Microsoft/vstest/issues/213). Since there is no way to find current user in linux machine. - // We are catching PlatformNotSupportedException for non windows machine. - try - { - _runUser = WindowsIdentity.GetCurrent().Name; - } - catch (PlatformNotSupportedException) - { - _runUser = string.Empty; - } - _created = DateTime.UtcNow; - _queued = DateTime.UtcNow; - _started = DateTime.UtcNow; - _finished = DateTime.UtcNow; - } } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunConfiguration.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunConfiguration.cs index 572cbafa18..0cf5b3ff7f 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunConfiguration.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunConfiguration.cs @@ -2,15 +2,12 @@ // 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.Xml; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; - using Microsoft.TestPlatform.Extensions.TrxLogger.XML; - -#nullable disable +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; @@ -81,7 +78,7 @@ public string RunDeploymentInDirectory { get { - Debug.Assert(_runDeploymentRoot != null, "runDeploymentRoot is null"); + TPDebug.Assert(_runDeploymentRoot != null, "runDeploymentRoot is null"); return Path.Combine(_runDeploymentRoot, DeploymentInDirectorySuffix); } } @@ -100,7 +97,7 @@ internal string RunDeploymentRootDirectory set { - Debug.Assert(!string.IsNullOrEmpty(value), "RunDeploymentRootDirectory.value should not be null or empty."); + TPDebug.Assert(!string.IsNullOrEmpty(value), "RunDeploymentRootDirectory.value should not be null or empty."); _runDeploymentRoot = value; } } @@ -116,7 +113,7 @@ internal string RunDeploymentRootDirectory /// /// The parameters. /// - public void Save(XmlElement element, XmlTestStoreParameters parameters) + public void Save(XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence helper = new(); @@ -127,14 +124,15 @@ public void Save(XmlElement element, XmlTestStoreParameters parameters) // When saving and loading a TRX file, we want to use the run deployment root directory based on where the TRX file // is being saved to or loaded from - if (parameters.TryGetValue(XmlFilePersistence.RootObjectType, out object filePersistenceRootObjectType) && + // REVIEW ME: NRE on parameters, is it expected? + if (parameters!.TryGetValue(XmlFilePersistence.RootObjectType, out object? filePersistenceRootObjectType) && (Type)filePersistenceRootObjectType == typeof(TestRun)) { - Debug.Assert( + TPDebug.Assert( parameters.ContainsKey(XmlFilePersistence.DirectoryPath), "TestRun is the type of the root object being saved to a file, but the DirectoryPath was not specified in the XML test store parameters"); - Debug.Assert( + TPDebug.Assert( !string.IsNullOrEmpty(_runDeploymentRoot), "TestRun is the type of the root object being saved to a file, but the run deployment root directory is null or empty"); @@ -144,7 +142,7 @@ public void Save(XmlElement element, XmlTestStoreParameters parameters) helper.SaveSimpleField( element, "Deployment/@runDeploymentRoot", - _trxFileHelper.MakePathRelative(_runDeploymentRoot, Path.GetDirectoryName(_runDeploymentRoot)), + _trxFileHelper.MakePathRelative(_runDeploymentRoot, Path.GetDirectoryName(_runDeploymentRoot)!), string.Empty); } else diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunConfigurationId.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunConfigurationId.cs index f0ef6b2cd0..4f698c2fed 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunConfigurationId.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunConfigurationId.cs @@ -3,8 +3,6 @@ using System; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunSummary.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunSummary.cs index 075c47779d..878f048254 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunSummary.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestRunSummary.cs @@ -6,8 +6,6 @@ using Microsoft.TestPlatform.Extensions.TrxLogger.XML; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -137,7 +135,7 @@ public TestRunSummary( /// /// The parameter /// - public void Save(XmlElement element, XmlTestStoreParameters parameters) + public void Save(XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence helper = new(); helper.SaveSingleFields(element, this, parameters); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestType.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestType.cs index 688a708400..fece20ebf5 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestType.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/TestType.cs @@ -5,8 +5,6 @@ using Microsoft.TestPlatform.Extensions.TrxLogger.XML; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// @@ -32,7 +30,7 @@ public Guid Id get { return _typeId; } } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is TestType tt && _typeId.Equals(tt._typeId); } @@ -54,7 +52,7 @@ public override int GetHashCode() /// /// The parameter /// - public void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence.SaveUsingReflection(element, this, null, parameters); } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UnitTestElement.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UnitTestElement.cs index 6d3cd5418e..ae4084b1bc 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UnitTestElement.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UnitTestElement.cs @@ -2,13 +2,11 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Diagnostics; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; using Microsoft.TestPlatform.Extensions.TrxLogger.XML; - -#nullable disable +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; @@ -17,7 +15,7 @@ namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// internal class UnitTestElement : TestElement, IXmlTestStoreCustom { - private string _codeBase; + private string? _codeBase; public UnitTestElement( Guid id, @@ -25,9 +23,9 @@ public UnitTestElement( string adapter, TestMethod testMethod) : base(id, name, adapter) { - Debug.Assert(!string.IsNullOrEmpty(adapter), "adapter is null"); - Debug.Assert(testMethod != null, "testMethod is null"); - Debug.Assert(testMethod != null && testMethod.ClassName != null, "className is null"); + TPDebug.Assert(!string.IsNullOrEmpty(adapter), "adapter is null"); + TPDebug.Assert(testMethod != null, "testMethod is null"); + TPDebug.Assert(testMethod != null && testMethod.ClassName != null, "className is null"); TestMethod = testMethod; } @@ -37,7 +35,7 @@ string IXmlTestStoreCustom.ElementName get { return Constants.UnitTestElementName; } } - string IXmlTestStoreCustom.NamespaceUri + string? IXmlTestStoreCustom.NamespaceUri { get { return null; } } @@ -58,7 +56,7 @@ public override TestType TestType /// /// Gets or sets the storage. /// - public string CodeBase + public string? CodeBase { get { return _codeBase; } @@ -78,7 +76,7 @@ public string CodeBase /// /// The parameter /// - public override void Save(System.Xml.XmlElement element, XmlTestStoreParameters parameters) + public override void Save(System.Xml.XmlElement element, XmlTestStoreParameters? parameters) { base.Save(element, parameters); XmlPersistence h = new(); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UnitTestResult.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UnitTestResult.cs index 0baf6033b0..be0b0e138c 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UnitTestResult.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UnitTestResult.cs @@ -5,8 +5,6 @@ using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; /// diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UriDataAttachment.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UriDataAttachment.cs index ed2a796d05..6faddb2897 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UriDataAttachment.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/UriDataAttachment.cs @@ -2,15 +2,12 @@ // 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.Xml; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; - using Microsoft.TestPlatform.Extensions.TrxLogger.XML; - -#nullable disable +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; @@ -36,8 +33,11 @@ internal class UriDataAttachment : IDataAttachment, IXmlTestStore public UriDataAttachment(string description, Uri uri, TrxFileHelper trxFileHelper) { _trxFileHelper = trxFileHelper; + EqtAssert.ParameterNotNull(description, nameof(description)); + EqtAssert.ParameterNotNull(uri, nameof(uri)); - Initialize(description, uri); + Description = description; + Uri = uri; } #region IDataAttachment Members @@ -65,7 +65,7 @@ public UriDataAttachment(string description, Uri uri, TrxFileHelper trxFileHelpe /// /// The parameter /// - public void Save(XmlElement element, XmlTestStoreParameters parameters) + public void Save(XmlElement element, XmlTestStoreParameters? parameters) { EqtAssert.ParameterNotNull(element, nameof(element)); @@ -94,8 +94,8 @@ public void Save(XmlElement element, XmlTestStoreParameters parameters) /// A clone of the instance, with the URI made absolute internal UriDataAttachment Clone(string baseDirectory, bool useAbsoluteUri) { - Debug.Assert(!string.IsNullOrEmpty(baseDirectory), "'baseDirectory' is null or empty"); - Debug.Assert(baseDirectory == baseDirectory.Trim(), "'baseDirectory' contains whitespace at the ends"); + TPDebug.Assert(!baseDirectory.IsNullOrEmpty(), "'baseDirectory' is null or empty"); + TPDebug.Assert(baseDirectory == baseDirectory.Trim(), "'baseDirectory' contains whitespace at the ends"); if (useAbsoluteUri != Uri.IsAbsoluteUri) { @@ -110,13 +110,4 @@ internal UriDataAttachment Clone(string baseDirectory, bool useAbsoluteUri) } #endregion - private void Initialize(string desc, Uri uri) - { - EqtAssert.ParameterNotNull(desc, nameof(desc)); - EqtAssert.ParameterNotNull(uri, nameof(uri)); - - Description = desc; - Uri = uri; - } - } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/WorkItems.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/WorkItems.cs index 930fec067a..8de1582d83 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/WorkItems.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/ObjectModel/WorkItems.cs @@ -6,12 +6,10 @@ using System.Xml; using Microsoft.TestPlatform.Extensions.TrxLogger.Utility; - using Microsoft.TestPlatform.Extensions.TrxLogger.XML; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; + #region WorkItem /// /// Stores an int which represents a workitem @@ -48,7 +46,7 @@ public int Id /// /// Value being compared to. /// True if the values are the same and false otherwise. - public override bool Equals(object other) + public override bool Equals(object? other) { return other is WorkItem otherItem && _id == otherItem._id; } @@ -79,7 +77,7 @@ public override string ToString() /// /// XmlElement element /// XmlTestStoreParameters parameters - public void Save(XmlElement element, XmlTestStoreParameters parameters) + public void Save(XmlElement element, XmlTestStoreParameters? parameters) { new XmlPersistence().SaveSingleFields(element, this, parameters); } @@ -176,7 +174,7 @@ public int[] ToArray() /// /// other collection /// true if the collections contain the same items - public override bool Equals(object obj) + public override bool Equals(object? obj) { bool result = false; @@ -216,7 +214,7 @@ public override int GetHashCode() return base.GetHashCode(); } - public override void Save(XmlElement element, XmlTestStoreParameters parameters) + public override void Save(XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence xmlPersistence = new(); xmlPersistence.SaveHashtable(_container, element, ".", ".", null, "Workitem", parameters); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/TrxLogger.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/TrxLogger.cs index af255948cf..12dfb6422a 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/TrxLogger.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/TrxLogger.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Text; @@ -26,8 +27,6 @@ using TrxLoggerObjectModel = Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource; -#nullable disable - namespace Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; /// @@ -58,43 +57,47 @@ internal TrxLogger(IFileHelper fileHelper, TrxFileHelper trxFileHelper) /// /// Cache the TRX file path /// - private string _trxFilePath; + private string? _trxFilePath; // The converter class private readonly Converter _converter; - private ConcurrentDictionary _results; - private ConcurrentDictionary _testElements; - private ConcurrentDictionary _entries; + private ConcurrentDictionary? _results; + private ConcurrentDictionary? _testElements; + private ConcurrentDictionary? _entries; // Caching results and inner test entries for constant time lookup for inner parents. - private ConcurrentDictionary _innerResults; - private ConcurrentDictionary _innerTestEntries; + private ConcurrentDictionary? _innerResults; + private ConcurrentDictionary? _innerTestEntries; private readonly TrxFileHelper _trxFileHelper; /// /// Specifies the run level "out" messages /// - private StringBuilder _runLevelStdOut; + private StringBuilder? _runLevelStdOut; // List of run level errors and warnings generated. These are logged in the Trx in the Results Summary. - private List _runLevelErrorsAndWarnings; + private List? _runLevelErrorsAndWarnings; private readonly string _trxFileExtension = ".trx"; /// /// Parameters dictionary for logger. Ex: {"LogFileName":"TestResults.trx"}. /// - private Dictionary _parametersDictionary; + private Dictionary? _parametersDictionary; /// /// Gets the directory under which default trx file and test results attachments should be saved. /// - private string _testResultsDirPath; + private string? _testResultsDirPath; #region ITestLogger + [MemberNotNullWhen(true, nameof(_testResultsDirPath), nameof(_results), nameof(_innerResults), nameof(_testElements), nameof(_entries), nameof(_innerTestEntries), nameof(_runLevelErrorsAndWarnings), nameof(_runLevelStdOut))] + private bool IsInitialized { get; set; } + /// + [MemberNotNull(nameof(_testResultsDirPath), nameof(_results), nameof(_innerResults), nameof(_testElements), nameof(_entries), nameof(_innerTestEntries), nameof(_runLevelErrorsAndWarnings), nameof(_runLevelStdOut))] public void Initialize(TestLoggerEvents events, string testResultsDirPath) { ValidateArg.NotNull(events, nameof(events)); @@ -106,10 +109,24 @@ public void Initialize(TestLoggerEvents events, string testResultsDirPath) events.TestRunComplete += TestRunCompleteHandler; _testResultsDirPath = testResultsDirPath; - InitializeInternal(); + _results = new ConcurrentDictionary(); + _innerResults = new ConcurrentDictionary(); + _testElements = new ConcurrentDictionary(); + _entries = new ConcurrentDictionary(); + _innerTestEntries = new ConcurrentDictionary(); + _runLevelErrorsAndWarnings = new List(); + LoggerTestRun = null; + TotalTestCount = 0; + PassedTestCount = 0; + FailedTestCount = 0; + _runLevelStdOut = new StringBuilder(); + TestRunStartTime = DateTime.UtcNow; + + IsInitialized = true; } /// + [MemberNotNull(nameof(_parametersDictionary))] public void Initialize(TestLoggerEvents events, Dictionary parameters) { ValidateArg.NotNull(parameters, nameof(parameters)); @@ -139,17 +156,19 @@ public void Initialize(TestLoggerEvents events, Dictionary param internal string GetRunLevelInformationalMessage() { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); return _runLevelStdOut.ToString(); } internal List GetRunLevelErrorsAndWarnings() { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); return _runLevelErrorsAndWarnings; } internal DateTime TestRunStartTime { get; private set; } - internal TestRun LoggerTestRun { get; private set; } + internal TestRun? LoggerTestRun { get; private set; } internal int TotalTestCount { get; private set; } @@ -159,17 +178,29 @@ internal List GetRunLevelErrorsAndWarnings() internal int TestResultCount { - get { return _results.Count; } + get + { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); + return _results.Count; + } } internal int UnitTestElementCount { - get { return _testElements.Count; } + get + { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); + return _testElements.Count; + } } internal int TestEntryCount { - get { return _entries.Count; } + get + { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); + return _entries.Count; + } } internal TrxLoggerObjectModel.TestOutcome TestResultOutcome { get; private set; } = TrxLoggerObjectModel.TestOutcome.Passed; @@ -187,10 +218,11 @@ internal int TestEntryCount /// /// Event args /// - internal void TestMessageHandler(object sender, TestRunMessageEventArgs e) + internal void TestMessageHandler(object? sender, TestRunMessageEventArgs e) { ValidateArg.NotNull(sender, nameof(sender)); ValidateArg.NotNull(e, nameof(e)); + TPDebug.Assert(IsInitialized, "Logger is not initialized"); RunInfo runMessage; switch (e.Level) @@ -222,7 +254,7 @@ internal void TestMessageHandler(object sender, TestRunMessageEventArgs e) /// /// The eventArgs. /// - internal void TestResultHandler(object sender, TestResultEventArgs e) + internal void TestResultHandler(object? sender, TestResultEventArgs e) { // Create test run if (LoggerTestRun == null) @@ -238,7 +270,7 @@ internal void TestResultHandler(object sender, TestResultEventArgs e) // Setting parent properties like parent result, parent test element, parent execution id. var parentExecutionId = _converter.GetParentExecutionId(e.Result); var parentTestResult = GetTestResult(parentExecutionId); - var parentTestElement = (parentTestResult != null) ? GetTestElement(parentTestResult.Id.TestId) : null; + var parentTestElement = parentTestResult != null ? GetTestElement(parentTestResult.Id.TestId) : null; // Switch to flat test results in case any parent related information is missing. if (parentTestResult == null || parentTestElement == null || parentExecutionId == Guid.Empty) @@ -282,7 +314,7 @@ internal void TestResultHandler(object sender, TestResultEventArgs e) /// /// Test run complete events arguments. /// - internal void TestRunCompleteHandler(object sender, TestRunCompleteEventArgs e) + internal void TestRunCompleteHandler(object? sender, TestRunCompleteEventArgs e) { // Create test run // If abort occurs there is no call to TestResultHandler which results in testRun not created. @@ -290,6 +322,8 @@ internal void TestRunCompleteHandler(object sender, TestRunCompleteEventArgs e) if (LoggerTestRun == null) CreateTestRun(); + TPDebug.Assert(IsInitialized, "Logger is not initialized"); + XmlPersistence helper = new(); XmlTestStoreParameters parameters = XmlTestStoreParameters.GetParameters(); XmlElement rootElement = helper.CreateRootElement("TestRun"); @@ -355,7 +389,7 @@ internal void TestRunCompleteHandler(object sender, TestRunCompleteEventArgs e) helper.SaveObject(runSummary, rootElement, "ResultSummary", parameters); ReserveTrxFilePath(); - PopulateTrxFile(_trxFilePath, rootElement); + PopulateTrxFile(_trxFilePath!, rootElement); } /// @@ -388,23 +422,6 @@ internal virtual void PopulateTrxFile(string trxFileName, XmlElement rootElement } } - // Initializes trx logger cache. - private void InitializeInternal() - { - _results = new ConcurrentDictionary(); - _innerResults = new ConcurrentDictionary(); - _testElements = new ConcurrentDictionary(); - _entries = new ConcurrentDictionary(); - _innerTestEntries = new ConcurrentDictionary(); - _runLevelErrorsAndWarnings = new List(); - LoggerTestRun = null; - TotalTestCount = 0; - PassedTestCount = 0; - FailedTestCount = 0; - _runLevelStdOut = new StringBuilder(); - TestRunStartTime = DateTime.UtcNow; - } - /// /// Add run level informational message /// @@ -413,13 +430,14 @@ private void InitializeInternal() /// private void AddRunLevelInformationalMessage(string message) { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); _runLevelStdOut.AppendLine(message); } // Handle the skipped test result private void HandleSkippedTest(ObjectModel.TestResult rsTestResult) { - Debug.Assert(rsTestResult.Outcome == ObjectModel.TestOutcome.Skipped, "Test Result should be skipped but it is " + rsTestResult.Outcome); + TPDebug.Assert(rsTestResult.Outcome == ObjectModel.TestOutcome.Skipped, "Test Result should be skipped but it is " + rsTestResult.Outcome); TestCase testCase = rsTestResult.TestCase; string testCaseName = !string.IsNullOrEmpty(testCase.DisplayName) ? testCase.DisplayName : testCase.FullyQualifiedName; @@ -459,11 +477,14 @@ private void ReserveTrxFilePath() private string AcquireTrxFileNamePath(out bool shouldOverwrite) { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); + TPDebug.Assert(_parametersDictionary is not null, "_parametersDictionary is null"); + shouldOverwrite = false; - var isLogFileNameParameterExists = _parametersDictionary.TryGetValue(TrxLoggerConstants.LogFileNameKey, out string logFileNameValue) && !string.IsNullOrWhiteSpace(logFileNameValue); - var isLogFilePrefixParameterExists = _parametersDictionary.TryGetValue(TrxLoggerConstants.LogFilePrefixKey, out string logFilePrefixValue) && !string.IsNullOrWhiteSpace(logFilePrefixValue); + var isLogFileNameParameterExists = _parametersDictionary.TryGetValue(TrxLoggerConstants.LogFileNameKey, out string? logFileNameValue) && !logFileNameValue.IsNullOrWhiteSpace(); + var isLogFilePrefixParameterExists = _parametersDictionary.TryGetValue(TrxLoggerConstants.LogFilePrefixKey, out string? logFilePrefixValue) && !logFilePrefixValue.IsNullOrWhiteSpace(); - string filePath = null; + string? filePath = null; if (isLogFilePrefixParameterExists) { @@ -477,7 +498,7 @@ private string AcquireTrxFileNamePath(out bool shouldOverwrite) } else if (isLogFileNameParameterExists) { - filePath = Path.Combine(_testResultsDirPath, logFileNameValue); + filePath = Path.Combine(_testResultsDirPath, logFileNameValue!); shouldOverwrite = true; } @@ -487,7 +508,7 @@ private string AcquireTrxFileNamePath(out bool shouldOverwrite) if (!Directory.Exists(trxFileDirPath)) { - Directory.CreateDirectory(trxFileDirPath); + Directory.CreateDirectory(trxFileDirPath!); } return filePath; @@ -498,6 +519,9 @@ private string AcquireTrxFileNamePath(out bool shouldOverwrite) /// private string SetDefaultTrxFilePath() { + TPDebug.Assert(LoggerTestRun != null, "LoggerTestRun is null"); + TPDebug.Assert(LoggerTestRun.RunConfiguration != null, "LoggerTestRun.RunConfiguration is null"); + TPDebug.Assert(IsInitialized, "Logger is not initialized"); var defaultTrxFileName = LoggerTestRun.RunConfiguration.RunDeploymentRootDirectory + ".trx"; return _trxFileHelper.GetNextIterationFileName(_testResultsDirPath, defaultTrxFileName, false); @@ -506,6 +530,7 @@ private string SetDefaultTrxFilePath() /// /// Creates test run. /// + [MemberNotNull(nameof(LoggerTestRun))] private void CreateTestRun() { // Skip run creation if already exists. @@ -533,9 +558,10 @@ private void CreateTestRun() /// /// /// Test result - private ITestResult GetTestResult(Guid executionId) + private ITestResult? GetTestResult(Guid executionId) { - ITestResult testResult = null; + TPDebug.Assert(IsInitialized, "Logger is not initialized"); + ITestResult? testResult = null; if (executionId != Guid.Empty) { @@ -553,8 +579,9 @@ private ITestResult GetTestResult(Guid executionId) /// /// /// - private ITestElement GetTestElement(Guid testId) + private ITestElement? GetTestElement(Guid testId) { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); _testElements.TryGetValue(testId, out var testElement); return testElement; } @@ -568,14 +595,15 @@ private ITestElement GetTestElement(Guid testId) /// /// /// Trx test element - private ITestElement GetOrCreateTestElement(Guid executionId, Guid parentExecutionId, TestType testType, ITestElement parentTestElement, ObjectModel.TestResult rockSteadyTestResult) + private ITestElement GetOrCreateTestElement(Guid executionId, Guid parentExecutionId, TestType testType, ITestElement? parentTestElement, ObjectModel.TestResult rockSteadyTestResult) { - ITestElement testElement = parentTestElement; + TPDebug.Assert(IsInitialized, "Logger is not initialized"); + ITestElement? testElement = parentTestElement; // For scenarios like data driven tests, test element is same as parent test element. if (parentTestElement != null && !parentTestElement.TestType.Equals(TrxLoggerConstants.OrderedTestType)) { - return testElement; + return testElement!; } TestCase testCase = rockSteadyTestResult.TestCase; @@ -613,13 +641,18 @@ private ITestElement GetOrCreateTestElement(Guid executionId, Guid parentExecuti /// /// /// - private void UpdateTestLinks(ITestElement testElement, ITestElement parentTestElement) + private static void UpdateTestLinks(ITestElement testElement, ITestElement? parentTestElement) { - if (parentTestElement != null && - parentTestElement.TestType.Equals(TrxLoggerConstants.OrderedTestType) && - !(parentTestElement as OrderedTestElement).TestLinks.ContainsKey(testElement.Id.Id)) + if (parentTestElement == null + || !parentTestElement.TestType.Equals(TrxLoggerConstants.OrderedTestType)) { - (parentTestElement as OrderedTestElement).TestLinks.Add(testElement.Id.Id, new TestLink(testElement.Id.Id, testElement.Name, testElement.Storage)); + return; + } + + var orderedTest = (OrderedTestElement)parentTestElement; + if (!orderedTest.TestLinks.ContainsKey(testElement.Id.Id)) + { + orderedTest.TestLinks.Add(testElement.Id.Id, new TestLink(testElement.Id.Id, testElement.Name, testElement.Storage)); } } @@ -635,10 +668,12 @@ private void UpdateTestLinks(ITestElement testElement, ITestElement parentTestEl /// /// Trx test result private ITestResult CreateTestResult(Guid executionId, Guid parentExecutionId, TestType testType, - ITestElement testElement, ITestElement parentTestElement, ITestResult parentTestResult, ObjectModel.TestResult rocksteadyTestResult) + ITestElement testElement, ITestElement? parentTestElement, ITestResult? parentTestResult, ObjectModel.TestResult rocksteadyTestResult) { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); // Create test result TrxLoggerObjectModel.TestOutcome testOutcome = _converter.ToOutcome(rocksteadyTestResult.Outcome); + TPDebug.Assert(LoggerTestRun != null, "LoggerTestRun is null"); var testResult = _converter.ToTestResult(testElement.Id.Id, executionId, parentExecutionId, testElement.Name, _testResultsDirPath, testType, testElement.CategoryId, testOutcome, LoggerTestRun, rocksteadyTestResult); @@ -652,7 +687,8 @@ private ITestResult CreateTestResult(Guid executionId, Guid parentExecutionId, T // Ordered test inner result scenario if (parentTestElement != null && parentTestElement.TestType.Equals(TrxLoggerConstants.OrderedTestType)) { - (parentTestResult as TestResultAggregation).InnerResults.Add(testResult); + TPDebug.Assert(parentTestResult is TestResultAggregation, "parentTestResult is not of type TestResultAggregation"); + ((TestResultAggregation)parentTestResult).InnerResults.Add(testResult); _innerResults.TryAdd(executionId, testResult); return testResult; } @@ -660,8 +696,10 @@ private ITestResult CreateTestResult(Guid executionId, Guid parentExecutionId, T // Data driven inner result scenario if (parentTestElement != null && parentTestElement.TestType.Equals(TrxLoggerConstants.UnitTestType)) { - (parentTestResult as TestResultAggregation).InnerResults.Add(testResult); - testResult.DataRowInfo = (parentTestResult as TestResultAggregation).InnerResults.Count; + TPDebug.Assert(parentTestResult is TestResultAggregation, "parentTestResult is not of type TestResultAggregation"); + var testResultAggregation = (TestResultAggregation)parentTestResult; + testResultAggregation.InnerResults.Add(testResult); + testResult.DataRowInfo = testResultAggregation.InnerResults.Count; testResult.ResultType = TrxLoggerConstants.InnerDataDrivenResultType; parentTestResult.ResultType = TrxLoggerConstants.ParentDataDrivenResultType; return testResult; @@ -677,8 +715,9 @@ private ITestResult CreateTestResult(Guid executionId, Guid parentExecutionId, T /// /// /// - private void UpdateTestEntries(Guid executionId, Guid parentExecutionId, ITestElement testElement, ITestElement parentTestElement) + private void UpdateTestEntries(Guid executionId, Guid parentExecutionId, ITestElement testElement, ITestElement? parentTestElement) { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); TestEntry te = new(testElement.Id, TestListCategory.UncategorizedResults.Id); te.ExecutionId = executionId; @@ -703,9 +742,10 @@ private void UpdateTestEntries(Guid executionId, Guid parentExecutionId, ITestEl /// /// /// Test entry - private TestEntry GetTestEntry(Guid executionId) + private TestEntry? GetTestEntry(Guid executionId) { - TestEntry testEntry = null; + TPDebug.Assert(IsInitialized, "Logger is not initialized"); + TestEntry? testEntry = null; if (executionId != Guid.Empty) { @@ -720,6 +760,9 @@ private TestEntry GetTestEntry(Guid executionId) private TrxLoggerObjectModel.TestOutcome ChangeTestOutcomeIfNecessary(TrxLoggerObjectModel.TestOutcome outcome) { + TPDebug.Assert(IsInitialized, "Logger is not initialized"); + TPDebug.Assert(_parametersDictionary is not null, "_parametersDictionary is null"); + // If no tests discovered/executed and TreatNoTestsAsError was set to True // We will return ResultSummary as Failed // Note : we only send the value of TreatNoTestsAsError if it is "True" diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Collection.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Collection.cs index dbdfcb4b67..36cf091257 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Collection.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Collection.cs @@ -3,13 +3,11 @@ using System.Collections; using System.Collections.Generic; -using System.Diagnostics; using System.Xml; using Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; using Microsoft.TestPlatform.Extensions.TrxLogger.XML; - -#nullable disable +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; namespace Microsoft.TestPlatform.Extensions.TrxLogger.Utility; @@ -30,7 +28,7 @@ private sealed class EqtBaseCollectionEnumerator : IEnumerator IEnumerable.GetEnumerator() /// Default behavior is to create child elements with name same as name of type T. /// Does not respect IXmlTestStoreCustom. /// - public virtual void Save(XmlElement element, XmlTestStoreParameters parameters) + public virtual void Save(XmlElement element, XmlTestStoreParameters? parameters) { XmlPersistence xmlPersistence = new(); xmlPersistence.SaveHashtable(_container, element, ".", ".", null, ChildElementName, parameters); diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Constants.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Constants.cs index fb09868c1f..2987b6e448 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Constants.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Constants.cs @@ -6,8 +6,6 @@ using Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.Utility; internal static class Constants diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs index 68594027a4..f83afcbadc 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs @@ -10,14 +10,13 @@ using System.Text; using Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource; using TrxObjectModel = Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.Utility; /// @@ -190,7 +189,7 @@ public List ToCollectionEntries(IEnumerable a return collectorEntries; } - public IList ToResultFiles(IEnumerable attachmentSets, TestRun testRun, string trxFileDirectory, + public IList ToResultFiles(IEnumerable? attachmentSets, TestRun testRun, string trxFileDirectory, List errorMessages) { List resultFiles = new(); @@ -295,7 +294,7 @@ public Guid GetTestId(TestCase rockSteadyTestCase) Guid testId = Guid.Empty; // Setting test id to tmi test id. - TestProperty tmiTestIdProperty = rockSteadyTestCase.Properties.FirstOrDefault( + TestProperty? tmiTestIdProperty = rockSteadyTestCase.Properties.FirstOrDefault( property => property.Id.Equals(Constants.TmiTestIdPropertyIdentifier)); if (tmiTestIdProperty != null) @@ -315,7 +314,7 @@ public Guid GetTestId(TestCase rockSteadyTestCase) /// Parent execution id. public Guid GetParentExecutionId(VisualStudio.TestPlatform.ObjectModel.TestResult testResult) { - TestProperty parentExecutionIdProperty = testResult.Properties.FirstOrDefault( + TestProperty? parentExecutionIdProperty = testResult.Properties.FirstOrDefault( property => property.Id.Equals(Constants.ParentExecutionIdPropertyIdentifier)); return parentExecutionIdProperty == null ? @@ -330,7 +329,7 @@ public Guid GetParentExecutionId(VisualStudio.TestPlatform.ObjectModel.TestResul /// Execution id. public Guid GetExecutionId(VisualStudio.TestPlatform.ObjectModel.TestResult testResult) { - TestProperty executionIdProperty = testResult.Properties.FirstOrDefault( + TestProperty? executionIdProperty = testResult.Properties.FirstOrDefault( property => property.Id.Equals(Constants.ExecutionIdPropertyIdentifier)); var executionId = Guid.Empty; @@ -351,8 +350,8 @@ public TestType GetTestType(VisualStudio.TestPlatform.ObjectModel.TestResult tes var testTypeGuid = Constants.UnitTestTypeGuid; // Get test type from property. default to unit test type. - TestProperty testTypeProperty = testResult.Properties.FirstOrDefault(property => property.Id.Equals(Constants.TestTypePropertyIdentifier)); - testTypeGuid = (testTypeProperty == null) ? testTypeGuid : testResult.GetPropertyValue(testTypeProperty, testTypeGuid); + TestProperty? testTypeProperty = testResult.Properties.FirstOrDefault(property => property.Id.Equals(Constants.TestTypePropertyIdentifier)); + testTypeGuid = testTypeProperty == null ? testTypeGuid : testResult.GetPropertyValue(testTypeProperty, testTypeGuid); // Currently trx supports ordered test and unit test. All tests except ordered test are modified as unit test type. return (testTypeGuid.Equals(Constants.OrderedTestTypeGuid)) ? @@ -436,7 +435,7 @@ private void UpdateTestResultAttachments(VisualStudio.TestPlatform.ObjectModel.T // Returns a list of collector entry private CollectorDataEntry ToCollectorEntry(AttachmentSet attachmentSet, Guid testResultExecutionId, TestRun testRun, string trxFileDirectory) { - string runDirectoryName = Path.Combine(trxFileDirectory, testRun.RunConfiguration.RunDeploymentRootDirectory); + string runDirectoryName = Path.Combine(trxFileDirectory, testRun.RunConfiguration!.RunDeploymentRootDirectory); string inDirectory = Path.Combine(runDirectoryName, "In"); string targetDirectory = inDirectory; @@ -455,11 +454,11 @@ private CollectorDataEntry ToCollectorEntry(AttachmentSet attachmentSet, Guid te List uriDataAttachments = new(); foreach (VisualStudio.TestPlatform.ObjectModel.UriDataAttachment uriDataAttachment in attachmentSet.Attachments) { - EqtTrace.Verbose("TrxLogger.ToCollectorEntry: Got attachment " + uriDataAttachment.Uri + " with description " + uriDataAttachment.Description); + EqtTrace.Verbose($"TrxLogger.ToCollectorEntry: Got attachment {uriDataAttachment.Uri} with description {uriDataAttachment.Description}"); string sourceFile = uriDataAttachment.Uri.LocalPath; _ = (Path.GetFullPath(sourceFile) == sourceFile); - Debug.Assert(Path.IsPathRooted(sourceFile), "Source file is not rooted"); + TPDebug.Assert(Path.IsPathRooted(sourceFile), "Source file is not rooted"); // copy the source file to the target location string targetFileName = _trxFileHelper.GetNextIterationFileName(targetDirectory, Path.GetFileName(sourceFile), false); @@ -478,7 +477,7 @@ private CollectorDataEntry ToCollectorEntry(AttachmentSet attachmentSet, Guid te } catch (Exception ex) { - EqtTrace.Error("Trxlogger: ToCollectorEntry: " + ex); + EqtTrace.Error($"Trxlogger.ToCollectorEntry: {ex}"); } } @@ -494,7 +493,7 @@ private CollectorDataEntry ToCollectorEntry(AttachmentSet attachmentSet, Guid te // Get the path to the result files private IList ToResultFiles(AttachmentSet attachmentSet, Guid testResultExecutionId, TestRun testRun, string trxFileDirectory) { - string runDirectoryName = Path.Combine(trxFileDirectory, testRun.RunConfiguration.RunDeploymentRootDirectory); + string runDirectoryName = Path.Combine(trxFileDirectory, testRun.RunConfiguration!.RunDeploymentRootDirectory); string testResultDirectory = Path.Combine(runDirectoryName, "In"); if (!Equals(testResultExecutionId, Guid.Empty)) @@ -514,9 +513,9 @@ private IList ToResultFiles(AttachmentSet attachmentSet, Guid testResult { string sourceFile = uriDataAttachment.Uri.IsAbsoluteUri ? uriDataAttachment.Uri.LocalPath : uriDataAttachment.Uri.ToString(); - EqtTrace.Verbose("TrxLogger: ToResultFiles: Got attachment " + uriDataAttachment.Uri + " with local path " + sourceFile); + EqtTrace.Verbose($"TrxLogger.ToResultFiles: Got attachment {uriDataAttachment.Uri} with local path {sourceFile}"); - Debug.Assert(Path.IsPathRooted(sourceFile), "Source file is not rooted"); + TPDebug.Assert(Path.IsPathRooted(sourceFile), "Source file is not rooted"); // copy the source file to the target location string targetFileName = _trxFileHelper.GetNextIterationFileName(testResultDirectory, Path.GetFileName(sourceFile), false); @@ -556,11 +555,11 @@ private void CopyFile(string sourceFile, string targetFile) /// /// /// Priority - private int GetPriority(TestCase rockSteadyTestCase) + private static int GetPriority(TestCase rockSteadyTestCase) { int priority = int.MaxValue; - Trait priorityTrait = rockSteadyTestCase.Traits?.FirstOrDefault(t => t.Name.Equals("Priority")); + Trait? priorityTrait = rockSteadyTestCase.Traits?.FirstOrDefault(t => t.Name.Equals("Priority")); if (priorityTrait != null && int.TryParse(priorityTrait.Value, out int priorityValue)) priority = priorityValue; @@ -572,11 +571,11 @@ private int GetPriority(TestCase rockSteadyTestCase) /// /// /// Owner - private string GetOwner(TestCase rockSteadyTestCase) + private static string GetOwner(TestCase rockSteadyTestCase) { - string owner = null; + string? owner = null; - Trait ownerTrait = rockSteadyTestCase.Traits?.FirstOrDefault(t => t.Name.Equals("Owner")); + Trait? ownerTrait = rockSteadyTestCase.Traits?.FirstOrDefault(t => t.Name.Equals("Owner")); if (ownerTrait != null) owner = ownerTrait.Value; @@ -590,7 +589,7 @@ private string GetOwner(TestCase rockSteadyTestCase) /// Fully qualified name. /// Source. /// Test class name. - private string GetTestClassName(string testName, string fullyQualifiedName, string source) + private static string GetTestClassName(string testName, string fullyQualifiedName, string source) { var className = "DefaultClassName"; @@ -644,23 +643,20 @@ private string GetTestClassName(string testName, string fullyQualifiedName, stri /// /// /// Trx test element - private TestElement CreateTestElement(Guid testId, string name, string fullyQualifiedName, string adapter, string source, TestType testType) + private static TestElement CreateTestElement(Guid testId, string name, string fullyQualifiedName, string adapter, string source, TestType testType) { - TestElement testElement; if (testType.Equals(Constants.OrderedTestType)) { - testElement = new OrderedTestElement(testId, name, adapter); + return new OrderedTestElement(testId, name, adapter); } - else - { - var codeBase = source; - var className = GetTestClassName(name, fullyQualifiedName, source); - var testMethodName = fullyQualifiedName.StartsWith($"{className}.") ? fullyQualifiedName.Remove(0, $"{className}.".Length) : fullyQualifiedName; - var testMethod = new TestMethod(testMethodName, className); - testElement = new UnitTestElement(testId, name, adapter, testMethod); - (testElement as UnitTestElement).CodeBase = codeBase; - } + var codeBase = source; + var className = GetTestClassName(name, fullyQualifiedName, source); + var testMethodName = fullyQualifiedName.StartsWith($"{className}.") ? fullyQualifiedName.Remove(0, $"{className}.".Length) : fullyQualifiedName; + var testMethod = new TestMethod(testMethodName, className); + + var testElement = new UnitTestElement(testId, name, adapter, testMethod); + testElement.CodeBase = codeBase; return testElement; } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/EqtAssert.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/EqtAssert.cs index dcc6b4f6eb..ed1eb968ca 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/EqtAssert.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/EqtAssert.cs @@ -3,11 +3,12 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; -using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource; +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; -#nullable disable +using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource; namespace Microsoft.TestPlatform.Extensions.TrxLogger.Utility; @@ -24,13 +25,13 @@ private EqtAssert() } /// - /// Verifies that the specified parameter is not null, Debug.Asserts and throws. + /// Verifies that the specified parameter is not null, TPDebug.Asserts and throws. /// /// Expression to check /// Comment to write public static void IsTrue(bool expression, string comment) { - Debug.Assert(expression, comment); + TPDebug.Assert(expression, comment); if (!expression) { throw new Exception(comment); @@ -38,14 +39,14 @@ public static void IsTrue(bool expression, string comment) } /// - /// Verifies that the specified parameter is not null, Debug.Asserts and throws. + /// Verifies that the specified parameter is not null, TPDebug.Asserts and throws. /// /// Parameter to check /// String - parameter name - public static void ParameterNotNull(object parameter, string parameterName) + public static void ParameterNotNull([ValidatedNotNull] object? parameter, [ValidatedNotNull] string parameterName) { AssertParameterNameNotNullOrEmpty(parameterName); - Debug.Assert(parameter != null, string.Format(CultureInfo.InvariantCulture, "'{0}' is null", parameterName)); + TPDebug.Assert(parameter != null, string.Format(CultureInfo.InvariantCulture, "'{0}' is null", parameterName)); if (parameter == null) { throw new ArgumentNullException(parameterName); @@ -53,15 +54,15 @@ public static void ParameterNotNull(object parameter, string parameterName) } /// - /// Verifies that the specified string parameter is neither null nor empty, Debug.Asserts and throws. + /// Verifies that the specified string parameter is neither null nor empty, TPDebug.Asserts and throws. /// /// Parameter to check /// String - parameter name - public static void StringNotNullOrEmpty(string parameter, string parameterName) + public static void StringNotNullOrEmpty([ValidatedNotNull] string? parameter, [ValidatedNotNull] string parameterName) { AssertParameterNameNotNullOrEmpty(parameterName); - Debug.Assert(!string.IsNullOrEmpty(parameter), string.Format(CultureInfo.InvariantCulture, "'{0}' is null or empty", parameterName)); - if (string.IsNullOrEmpty(parameter)) + TPDebug.Assert(!parameter.IsNullOrEmpty(), string.Format(CultureInfo.InvariantCulture, "'{0}' is null or empty", parameterName)); + if (parameter.IsNullOrEmpty()) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, TrxLoggerResources.Common_CannotBeNullOrEmpty)); } @@ -72,8 +73,8 @@ public static void StringNotNullOrEmpty(string parameter, string parameterName) /// /// The parameter name to verify [Conditional("DEBUG")] - private static void AssertParameterNameNotNullOrEmpty(string parameterName) + private static void AssertParameterNameNotNullOrEmpty([ValidatedNotNull] string? parameterName) { - Debug.Assert(!string.IsNullOrEmpty(parameterName), "'parameterName' is null or empty"); + TPDebug.Assert(!parameterName.IsNullOrEmpty(), "'parameterName' is null or empty"); } } diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/TestRunDirectories.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/TestRunDirectories.cs index 1f3715c335..bbe6b85323 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/TestRunDirectories.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/TestRunDirectories.cs @@ -3,8 +3,6 @@ using System; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.Utility; /// diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/TrxFileHelper.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/TrxFileHelper.cs index 3cc16d169c..7bf8928a9e 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/TrxFileHelper.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/TrxFileHelper.cs @@ -9,9 +9,9 @@ using System.Text; using System.Text.RegularExpressions; -using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource; +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; -#nullable disable +using TrxLoggerResources = Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger.Resources.TrxResource; namespace Microsoft.TestPlatform.Extensions.TrxLogger.Utility; @@ -191,7 +191,7 @@ public string MakePathRelative(string path, string basePath) string[] pathTokens = path.Split(delimiters); string[] basePathTokens = basePath.Split(delimiters); - Debug.Assert(pathTokens.Length > 0 && basePathTokens.Length > 0); + TPDebug.Assert(pathTokens.Length > 0 && basePathTokens.Length > 0); int max = Math.Min(pathTokens.Length, basePathTokens.Length); // Skip all of the empty tokens that result from things like "\dir1" @@ -265,7 +265,7 @@ public string MakePathRelative(string path, string basePath) /// private static bool IsReservedFileName(string fileName) { - Debug.Assert(!string.IsNullOrEmpty(fileName), "FileHelper.IsReservedFileName: the argument is null or empty string!"); + TPDebug.Assert(!string.IsNullOrEmpty(fileName), "FileHelper.IsReservedFileName: the argument is null or empty string!"); if (string.IsNullOrEmpty(fileName)) { return false; @@ -304,9 +304,9 @@ private static string GetNextIterationNameHelper( string originalName, IterationHelper helper) { - Debug.Assert(!string.IsNullOrEmpty(baseDirectoryName), "baseDirectoryname is null"); - Debug.Assert(!string.IsNullOrEmpty(originalName), "originalName is Null"); - Debug.Assert(helper != null, "helper is null"); + TPDebug.Assert(!baseDirectoryName.IsNullOrEmpty(), "baseDirectoryname is null"); + TPDebug.Assert(!originalName.IsNullOrEmpty(), "originalName is Null"); + TPDebug.Assert(helper != null, "helper is null"); uint iteration = 0; do @@ -342,7 +342,7 @@ private abstract class IterationHelper /// internal static string FormatIteration(string baseName, uint iteration) { - Debug.Assert(!string.IsNullOrEmpty(baseName), "basename is null"); + TPDebug.Assert(!string.IsNullOrEmpty(baseName), "basename is null"); var tryMe = string.Format( CultureInfo.InvariantCulture, @@ -372,7 +372,7 @@ internal FileIterationHelper(bool checkMatchingDirectory) internal override string NextIteration(string baseName, uint iteration) { - Debug.Assert(!string.IsNullOrEmpty(baseName), "baseName is null"); + TPDebug.Assert(!string.IsNullOrEmpty(baseName), "baseName is null"); string withoutExtensionName = Path.GetFileNameWithoutExtension(baseName); string tryMe = FormatIteration(withoutExtensionName, iteration); @@ -386,7 +386,7 @@ internal override string NextIteration(string baseName, uint iteration) internal override bool IsValidIteration(string path) { - Debug.Assert(!string.IsNullOrEmpty(path), "path is null"); + TPDebug.Assert(!string.IsNullOrEmpty(path), "path is null"); if (File.Exists(path) || Directory.Exists(path)) { diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/Attributes.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/Attributes.cs index d0eb5564d7..4b18c574a3 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/Attributes.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/Attributes.cs @@ -3,8 +3,6 @@ using System; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.XML; /// @@ -16,7 +14,7 @@ internal abstract class StoreXmlAttribute : Attribute /// /// simple xpath location. only element and attribute names can be used. /// - public string Location; + public string? Location; /// /// Initializes a new instance of the class. @@ -31,7 +29,7 @@ public StoreXmlAttribute() /// /// The location. /// - public StoreXmlAttribute(string location) + public StoreXmlAttribute(string? location) { Location = location; } @@ -43,7 +41,7 @@ public StoreXmlAttribute(string location) [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] internal sealed class StoreXmlSimpleFieldAttribute : StoreXmlAttribute { - public object DefaultValue; + public object? DefaultValue; /// /// Initializes a new instance of the class. @@ -81,7 +79,7 @@ public StoreXmlSimpleFieldAttribute(object defaultValue) : this(null, defaultVal /// /// The default value. /// - public StoreXmlSimpleFieldAttribute(string location, object defaultValue) + public StoreXmlSimpleFieldAttribute(string? location, object defaultValue) : base(location) { DefaultValue = defaultValue; diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlFilePersistence.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlFilePersistence.cs index 94f05b1592..77419e3676 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlFilePersistence.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlFilePersistence.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.TestPlatform.Extensions.TrxLogger.XML; internal class XmlFilePersistence : XmlPersistence diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlPersistence.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlPersistence.cs index 48198f6fb1..8d57e144cd 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlPersistence.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlPersistence.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; -using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; @@ -15,12 +14,11 @@ using System.Xml; using Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; +using Microsoft.VisualStudio.TestPlatform.Extensions.TrxLogger; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using TrxObjectModel = Microsoft.TestPlatform.Extensions.TrxLogger.ObjectModel; -#nullable disable - namespace Microsoft.TestPlatform.Extensions.TrxLogger.XML; /// @@ -52,7 +50,7 @@ public DuplicateKeyLoadException(object key, string message) /// Key that was a duplicate /// The duplicate-key exception message /// The inner exception - public DuplicateKeyLoadException(object key, string message, Exception innerException) + public DuplicateKeyLoadException(object key, string message, Exception? innerException) : base(message, innerException) { Key = key; @@ -151,7 +149,7 @@ private XmlElement CreateRootElement(string name, string namespaceUri) XmlDocument dom = new(); dom.AppendChild(dom.CreateXmlDeclaration("1.0", "UTF-8", null)); - return (XmlElement)dom.AppendChild(dom.CreateElement(_prefix, name, namespaceUri)); + return (XmlElement)dom.AppendChild(dom.CreateElement(_prefix, name, namespaceUri))!; } #region PublicSaveDataInTrx @@ -168,7 +166,7 @@ private XmlElement CreateRootElement(string name, string namespaceUri) /// /// The parameters. /// - public void SaveSingleFields(XmlElement parentXml, object instance, XmlTestStoreParameters parameters) + public void SaveSingleFields(XmlElement parentXml, object instance, XmlTestStoreParameters? parameters) { SaveSingleFields(parentXml, instance, null, parameters); } @@ -188,7 +186,7 @@ public void SaveSingleFields(XmlElement parentXml, object instance, XmlTestStore /// /// The parameters. /// - public void SaveSingleFields(XmlElement parentXml, object instance, Type requestedType, XmlTestStoreParameters parameters) + public void SaveSingleFields(XmlElement parentXml, object? instance, Type? requestedType, XmlTestStoreParameters? parameters) { if (instance == null) { @@ -199,17 +197,19 @@ public void SaveSingleFields(XmlElement parentXml, object instance, Type request foreach (FieldPersistenceInfo info in GetFieldInfos(type)) { - object fieldValue = info.FieldInfo.GetValue(instance); - if (fieldValue != null) + object? fieldValue = info.FieldInfo.GetValue(instance); + if (fieldValue == null) { - if (info.FieldAttribute != null) - { - SaveObject(fieldValue, parentXml, info.Location, parameters); - } - else if (info.SimpleFieldAttribute != null) - { - SaveSimpleField(parentXml, info.Location, fieldValue, info.SimpleFieldAttribute.DefaultValue); - } + continue; + } + + if (info.FieldAttribute != null) + { + SaveObject(fieldValue, parentXml, info.Location, parameters); + } + else if (info.SimpleFieldAttribute != null) + { + SaveSimpleField(parentXml, info.Location!, fieldValue, info.SimpleFieldAttribute.DefaultValue); } } } @@ -229,26 +229,29 @@ public void SaveSingleFields(XmlElement parentXml, object instance, Type request /// /// The parameters. /// - public void SaveObject(object objectToSave, XmlElement parentXml, string location, XmlTestStoreParameters parameters) + public void SaveObject(object? objectToSave, XmlElement parentXml, string? location, XmlTestStoreParameters? parameters) { - if (objectToSave != null && location != null) + if (objectToSave == null || location == null) { - string nameSpaceUri = _namespaceUri; - if (objectToSave is IXmlTestStoreCustom customStore) - { - nameSpaceUri = customStore.NamespaceUri; - } + return; + } - XmlNode xmlNode = EnsureLocationExists(parentXml, location, nameSpaceUri); - SaveObject(objectToSave, xmlNode, parameters); + string? nameSpaceUri = _namespaceUri; + if (objectToSave is IXmlTestStoreCustom customStore) + { + nameSpaceUri = customStore.NamespaceUri; + } - if (xmlNode is XmlElement element && - !element.HasAttributes && - !element.HasChildNodes && - string.IsNullOrEmpty(element.InnerText)) - { - element.ParentNode.RemoveChild(element); // get rid of empty elements to keep the xml clean - } + XmlNode? xmlNode = EnsureLocationExists(parentXml, location, nameSpaceUri); + TPDebug.Assert(xmlNode != null, "EnsureLocationExists should have returned a node"); + SaveObject(objectToSave, xmlNode, parameters); + + if (xmlNode is XmlElement element && + !element.HasAttributes && + !element.HasChildNodes && + element.InnerText.IsNullOrEmpty()) + { + element.ParentNode!.RemoveChild(element); // get rid of empty elements to keep the xml clean } } @@ -264,7 +267,7 @@ public void SaveObject(object objectToSave, XmlElement parentXml, string locatio /// /// The parameters. /// - public void SaveObject(object objectToSave, XmlNode nodeToSaveAt, XmlTestStoreParameters parameters) + public void SaveObject(object objectToSave, XmlNode nodeToSaveAt, XmlTestStoreParameters? parameters) { SaveObject(objectToSave, nodeToSaveAt, parameters, null); } @@ -284,18 +287,20 @@ public void SaveObject(object objectToSave, XmlNode nodeToSaveAt, XmlTestStorePa /// /// The default value. /// - public void SaveObject(object objectToSave, XmlNode nodeToSaveAt, XmlTestStoreParameters parameters, object defaultValue) + public void SaveObject(object? objectToSave, XmlNode nodeToSaveAt, XmlTestStoreParameters? parameters, object? defaultValue) { - if (objectToSave != null) + if (objectToSave == null) { - if (objectToSave is IXmlTestStore persistable) - { - persistable.Save((XmlElement)nodeToSaveAt, parameters); - } - else - { - SaveSimpleData(objectToSave, nodeToSaveAt, defaultValue); - } + return; + } + + if (objectToSave is IXmlTestStore persistable) + { + persistable.Save((XmlElement)nodeToSaveAt, parameters); + } + else + { + SaveSimpleData(objectToSave, nodeToSaveAt, defaultValue); } } @@ -314,14 +319,15 @@ public void SaveObject(object objectToSave, XmlNode nodeToSaveAt, XmlTestStorePa /// /// The default value. /// - public void SaveSimpleField(XmlElement xml, string location, object value, object defaultValue) + public void SaveSimpleField(XmlElement xml, string location, object? value, object? defaultValue) { if (value == null || value.Equals(defaultValue)) { return; } - XmlNode saveTarget = EnsureLocationExists(xml, location); + XmlNode? saveTarget = EnsureLocationExists(xml, location); + TPDebug.Assert(saveTarget != null, "EnsureLocationExists should have returned a node"); SaveSimpleData(value, saveTarget, defaultValue); } @@ -342,33 +348,39 @@ public void SaveGuid(XmlElement xml, string location, Guid guid) SaveSimpleField(xml, location, guid.ToString(), EmptyGuidString); } - public void SaveHashtable(Hashtable ht, XmlElement element, string location, string keyLocation, string valueLocation, string itemElementName, XmlTestStoreParameters parameters) + public void SaveHashtable(Hashtable ht, XmlElement element, string location, string keyLocation, string? valueLocation, string itemElementName, XmlTestStoreParameters? parameters) { - if (ht != null && ht.Count > 0) + if (ht == null || ht.Count <= 0) { - XmlElement dictionaryElement = (XmlElement)EnsureLocationExists(element, location); - foreach (DictionaryEntry de in ht) - { - XmlElement itemXml = CreateElement(dictionaryElement, itemElementName); + return; + } - SaveObject(de.Key, itemXml, keyLocation, parameters); - SaveObject(de.Value, itemXml, valueLocation, parameters); - } + XmlElement? dictionaryElement = (XmlElement?)EnsureLocationExists(element, location); + TPDebug.Assert(dictionaryElement != null, "EnsureLocationExists should have returned a node"); + foreach (DictionaryEntry de in ht) + { + XmlElement itemXml = CreateElement(dictionaryElement, itemElementName); + + SaveObject(de.Key, itemXml, keyLocation, parameters); + SaveObject(de.Value, itemXml, valueLocation, parameters); } } public void SaveStringDictionary(StringDictionary dict, XmlElement element, string location, string keyLocation, string valueLocation, string itemElementName, XmlTestStoreParameters parameters) { - if (dict != null && dict.Count > 0) + if (dict == null || dict.Count <= 0) { - XmlElement dictionaryElement = (XmlElement)EnsureLocationExists(element, location); - foreach (DictionaryEntry de in dict) - { - XmlElement itemXml = CreateElement(dictionaryElement, itemElementName); + return; + } - SaveObject(de.Key, itemXml, keyLocation, parameters); - SaveObject(de.Value, itemXml, valueLocation, parameters); - } + XmlElement? dictionaryElement = (XmlElement?)EnsureLocationExists(element, location); + TPDebug.Assert(dictionaryElement != null, "EnsureLocationExists should have returned a node"); + foreach (DictionaryEntry de in dict) + { + XmlElement itemXml = CreateElement(dictionaryElement, itemElementName); + + SaveObject(de.Key, itemXml, keyLocation, parameters); + SaveObject(de.Value, itemXml, valueLocation, parameters); } } @@ -394,16 +406,19 @@ public void SaveStringDictionary(StringDictionary dict, XmlElement element, stri /// /// The parameters. /// - public void SaveIEnumerable(IEnumerable list, XmlElement element, string listXmlElement, string itemLocation, string itemElementName, XmlTestStoreParameters parameters) + public void SaveIEnumerable(IEnumerable? list, XmlElement element, string listXmlElement, string itemLocation, string? itemElementName, XmlTestStoreParameters? parameters) { - if (list != null && list.GetEnumerator().MoveNext()) + if (list == null || !list.GetEnumerator().MoveNext()) { - XmlElement listElement = (XmlElement)EnsureLocationExists(element, listXmlElement); - foreach (object item in list) - { - XmlElement itemXml = CreateElement(listElement, itemElementName, item); - SaveObject(item, itemXml, itemLocation, parameters); - } + return; + } + + XmlElement? listElement = (XmlElement?)EnsureLocationExists(element, listXmlElement); + TPDebug.Assert(listElement != null, "EnsureLocationExists should have returned a node"); + foreach (object item in list) + { + XmlElement itemXml = CreateElement(listElement, itemElementName, item); + SaveObject(item, itemXml, itemLocation, parameters); } } @@ -432,14 +447,17 @@ public void SaveIEnumerable(IEnumerable list, XmlElement element, string listXml /// public void SaveList(IList list, XmlElement element, string listXmlElement, string itemLocation, string itemElementName, XmlTestStoreParameters parameters) { - if (list != null && list.Count > 0) + if (list == null || list.Count <= 0) { - XmlElement listElement = (XmlElement)EnsureLocationExists(element, listXmlElement); - foreach (V item in list) - { - XmlElement itemXml = CreateElement(listElement, itemElementName, item); - SaveObject(item, itemXml, itemLocation, parameters); - } + return; + } + + XmlElement? listElement = (XmlElement?)EnsureLocationExists(element, listXmlElement); + TPDebug.Assert(listElement != null, "EnsureLocationExists should have returned a node"); + foreach (V item in list) + { + XmlElement itemXml = CreateElement(listElement, itemElementName, item!); + SaveObject(item, itemXml, itemLocation, parameters); } } @@ -447,7 +465,7 @@ public void SaveList(IList list, XmlElement element, string listXmlElement public void SaveCounters(XmlElement xml, string location, int[] counters) { - xml = (XmlElement)LocationToXmlNode(xml, location); + xml = (XmlElement)LocationToXmlNode(xml, location)!; for (int i = 0; i < counters.Length; i++) { @@ -463,7 +481,7 @@ public void SaveCounters(XmlElement xml, string location, int[] counters) #endregion List - internal static void SaveUsingReflection(XmlElement element, object instance, Type requestedType, XmlTestStoreParameters parameters) + internal static void SaveUsingReflection(XmlElement element, object instance, Type? requestedType, XmlTestStoreParameters? parameters) { XmlPersistence helper = new(); helper.SaveSingleFields(element, instance, requestedType, parameters); @@ -555,11 +573,11 @@ private static string DateTimeToString(DateTime dateTime) } } - private static string GetFieldLocation(FieldInfo fieldInfo) + private static string? GetFieldLocation(FieldInfo fieldInfo) { - string location = null; + string? location = null; - StoreXmlAttribute locationAttribute = GetAttribute(fieldInfo); + StoreXmlAttribute? locationAttribute = GetAttribute(fieldInfo); if (locationAttribute != null) { location = locationAttribute.Location ?? GetDefaultFieldLocation(fieldInfo); @@ -586,14 +604,14 @@ private static bool ImplementsIXmlTestStore(Type type) return type.GetTypeInfo().GetInterface(typeof(IXmlTestStore).Name) != null; } - private static T GetAttribute(FieldInfo fieldInfo) where T : Attribute + private static T? GetAttribute(FieldInfo fieldInfo) where T : Attribute { var attributes = fieldInfo.GetCustomAttributes(typeof(T), false).ToArray(); return attributes.Length > 0 ? (T)attributes[0] : default; } - private void SaveSimpleData(object value, XmlNode nodeToSaveAt, object defaultValue) + private static void SaveSimpleData(object? value, XmlNode nodeToSaveAt, object? defaultValue) { if (value == null || value.Equals(defaultValue)) { @@ -602,15 +620,15 @@ private void SaveSimpleData(object value, XmlNode nodeToSaveAt, object defaultVa Type valueType = value.GetType(); - string valueToSave; + string? valueToSave; if (valueType == BoolType) { - valueToSave = value.ToString().ToLowerInvariant(); + valueToSave = value.ToString()!.ToLowerInvariant(); } else if (valueType == ByteArrayType) { // Use only for Arrays, Collections and Lists. E.g. string is also IEnumerable. - valueToSave = Convert.ToBase64String(value as byte[]); + valueToSave = Convert.ToBase64String((byte[])value); } else if (valueType == DateTimeType) { @@ -636,6 +654,7 @@ private void SaveSimpleData(object value, XmlNode nodeToSaveAt, object defaultVa valueToSave = RemoveInvalidXmlChar(valueToSave); if (nodeToSaveAt is XmlElement elementToSaveAt) { + TPDebug.Assert(valueToSave is not null, "valueToSave is null"); elementToSaveAt.InnerText = valueToSave; } else @@ -644,26 +663,26 @@ private void SaveSimpleData(object value, XmlNode nodeToSaveAt, object defaultVa } } - public XmlNode EnsureLocationExists(XmlElement xml, string location) + public XmlNode? EnsureLocationExists(XmlElement xml, string location) { return EnsureLocationExists(xml, location, _namespaceUri); } - private static string RemoveInvalidXmlChar(string str) + private static string? RemoveInvalidXmlChar(string? str) { - if (str != null) + if (str == null) { - // From xml spec (http://www.w3.org/TR/xml/#charsets) valid chars: - // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] - - // we are handling only #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] - // because C# support unicode character in range \u0000 to \uFFFF - MatchEvaluator evaluator = new(ReplaceInvalidCharacterWithUniCodeEscapeSequence); - string invalidChar = @"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD]"; - return Regex.Replace(str, invalidChar, evaluator); + return null; } - return str; + // From xml spec (http://www.w3.org/TR/xml/#charsets) valid chars: + // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + + // we are handling only #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] + // because C# support unicode character in range \u0000 to \uFFFF + MatchEvaluator evaluator = new(ReplaceInvalidCharacterWithUniCodeEscapeSequence); + string invalidChar = @"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD]"; + return Regex.Replace(str, invalidChar, evaluator); } private static string ReplaceInvalidCharacterWithUniCodeEscapeSequence(Match match) @@ -672,9 +691,9 @@ private static string ReplaceInvalidCharacterWithUniCodeEscapeSequence(Match mat return string.Format(@"\u{0:x4}", (ushort)x); } - private XmlNode EnsureLocationExists(XmlElement xml, string location, string nameSpaceUri) + private XmlNode? EnsureLocationExists(XmlElement xml, string location, string? nameSpaceUri) { - XmlNode node = LocationToXmlNode(xml, location); + XmlNode? node = LocationToXmlNode(xml, location); if (node != null) { return node; @@ -692,7 +711,7 @@ private XmlNode EnsureLocationExists(XmlElement xml, string location, string nam string[] parts = location.Split(new char[] { '/' }, 2); string firstPart = parts[0]; - XmlNode firstChild = LocationToXmlNode(xml, firstPart); + XmlNode? firstChild = LocationToXmlNode(xml, firstPart); if (firstChild == null) { firstChild = CreateElement(xml, firstPart, GetNamespaceUriOrDefault(nameSpaceUri)); @@ -702,7 +721,7 @@ private XmlNode EnsureLocationExists(XmlElement xml, string location, string nam } } - private string GetNamespaceUriOrDefault(string nameSpaceUri) + private string GetNamespaceUriOrDefault(string? nameSpaceUri) { return nameSpaceUri ?? _namespaceUri; } @@ -718,9 +737,9 @@ private XmlElement CreateElement(XmlElement xml, string name) return CreateElement(xml, name, _namespaceUri); } - private XmlElement CreateElement(XmlElement xml, string name, string elementNamespaceUri) + private XmlElement CreateElement(XmlElement xml, string name, string? elementNamespaceUri) { - return (XmlElement)xml.AppendChild(xml.OwnerDocument.CreateElement(_prefix, name, elementNamespaceUri)); + return (XmlElement)xml.AppendChild(xml.OwnerDocument.CreateElement(_prefix, name, elementNamespaceUri))!; } /// @@ -730,7 +749,7 @@ private XmlElement CreateElement(XmlElement xml, string name, string elementName /// The local name of the new element. /// the object for which element has to create /// a new XmlElement attached to the parent - private XmlElement CreateElement(XmlElement parent, string name, object instance) + private XmlElement CreateElement(XmlElement parent, string? name, object instance) { if (name != null) { @@ -739,13 +758,14 @@ private XmlElement CreateElement(XmlElement parent, string name, object instance else { NewElementCreateData createData = GetElementCreateData(instance); + TPDebug.Assert(createData.ElementName is not null, "createData.ElementName is null"); return CreateElement(parent, createData.ElementName, createData.NamespaceUri); } } private NewElementCreateData GetElementCreateData(object persistee) { - Debug.Assert(persistee != null, "persistee is null"); + TPDebug.Assert(persistee != null, "persistee is null"); NewElementCreateData toReturn = new(); if (persistee is IXmlTestStoreCustom custom) @@ -767,7 +787,7 @@ private NewElementCreateData GetElementCreateData(object persistee) return toReturn; } - private XmlNode LocationToXmlNode(XmlElement element, string location) + private XmlNode? LocationToXmlNode(XmlElement element, string location) { location = ProcessXPathQuery(location); @@ -777,7 +797,7 @@ private XmlNode LocationToXmlNode(XmlElement element, string location) } catch (System.Xml.XPath.XPathException e) { - throw new Exception("The persistence location is invalid. Element: '" + element.Name + "', location: '" + location + "'", e); + throw new Exception($"The persistence location is invalid. Element: '{element.Name}', location: '{location}'", e); } } @@ -827,9 +847,9 @@ private string ProcessXPathQuery(string queryIn) private class NewElementCreateData { - public string NamespaceUri { get; set; } + public string? NamespaceUri { get; set; } - public string ElementName { get; set; } + public string? ElementName { get; set; } } /// @@ -839,13 +859,13 @@ private class FieldPersistenceInfo { internal readonly FieldInfo FieldInfo; - internal readonly string Location; + internal readonly string? Location; - internal readonly StoreXmlAttribute Attribute; + internal readonly StoreXmlAttribute? Attribute; - internal readonly StoreXmlSimpleFieldAttribute SimpleFieldAttribute; + internal readonly StoreXmlSimpleFieldAttribute? SimpleFieldAttribute; - internal readonly StoreXmlFieldAttribute FieldAttribute; + internal readonly StoreXmlFieldAttribute? FieldAttribute; internal FieldPersistenceInfo(FieldInfo fieldInfo) { diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs index c0a756e51b..fd2d992697 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs @@ -553,6 +553,7 @@ bool SilentlyForceToX64() internal /* for testing purposes */ void ForwardDotnetRootEnvironmentVariable(TestProcessStartInfo startInfo) { + TPDebug.Assert(_targetFramework is not null, "Initialize must have been called before this method."); const string prefix = "VSTEST_WINAPPHOST_"; const string dotnetRoot = "DOTNET_ROOT"; string vstestDotnetRootEnvName = $"{prefix}{dotnetRoot}(x86)"; diff --git a/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/TrxLoggerTests.cs b/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/TrxLoggerTests.cs index a066580796..bb7cae86b9 100644 --- a/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/TrxLoggerTests.cs +++ b/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/TrxLoggerTests.cs @@ -36,7 +36,7 @@ public class TrxLoggerTests private static readonly string DefaultLogFileNameParameterValue = "logfilevalue.trx"; private readonly Mock _events; - private readonly Dictionary _parameters; + private readonly Dictionary _parameters; private TestableTrxLogger _testableTrxLogger; @@ -45,7 +45,7 @@ public TrxLoggerTests() _events = new Mock(); _testableTrxLogger = new TestableTrxLogger(); - _parameters = new Dictionary(2) + _parameters = new Dictionary(2) { [DefaultLoggerParameterNames.TestRunDirectory] = DefaultTestRunDirectory, [TrxLoggerConstants.LogFileNameKey] = DefaultLogFileNameParameterValue @@ -66,7 +66,7 @@ public void Cleanup() public void InitializeShouldThrowExceptionIfEventsIsNull() { Assert.ThrowsException( - () => _testableTrxLogger.Initialize(null, _parameters)); + () => _testableTrxLogger.Initialize(null!, _parameters)); } [TestMethod] @@ -83,7 +83,7 @@ public void InitializeShouldThrowExceptionIfTestRunDirectoryIsEmptyOrNull() () => { var events = new Mock(); - _parameters[DefaultLoggerParameterNames.TestRunDirectory] = null; + _parameters[DefaultLoggerParameterNames.TestRunDirectory] = null!; _testableTrxLogger.Initialize(events.Object, _parameters); }); } @@ -105,7 +105,7 @@ public void InitializeShouldThrowExceptionIfParametersAreEmpty() [TestMethod] public void TestMessageHandlerShouldThrowExceptionIfEventArgsIsNull() { - Assert.ThrowsException(() => _testableTrxLogger.TestMessageHandler(new object(), default)); + Assert.ThrowsException(() => _testableTrxLogger.TestMessageHandler(new object(), default!)); } [TestMethod] @@ -153,7 +153,7 @@ public void TestResultHandlerShouldCaptureStartTimeInSummaryWithTimeStampDuringI _testableTrxLogger.TestResultHandler(new object(), e.Object); - Assert.AreEqual(_testableTrxLogger.TestRunStartTime, _testableTrxLogger.LoggerTestRun.Started); + Assert.AreEqual(_testableTrxLogger.TestRunStartTime, _testableTrxLogger.LoggerTestRun?.Started); } [TestMethod] @@ -614,7 +614,7 @@ public void OutcomeOfRunWillBeCompletedIfNoTestsFails() public void TheDefaultTrxFileNameShouldNotHaveWhiteSpace() { // To create default trx file, log file parameter should be null. - _parameters[TrxLoggerConstants.LogFileNameKey] = null; + _parameters[TrxLoggerConstants.LogFileNameKey] = null!; _testableTrxLogger.Initialize(_events.Object, _parameters); MakeTestRunComplete(); @@ -885,7 +885,7 @@ private void ValidateTestIdAndNameInTrx(bool isMstestAdapter) ValidateResultAttributesInTrx(_testableTrxLogger.TrxFile!, testCase.Id, testCase.DisplayName, isMstestAdapter); } - private void ValidateResultAttributesInTrx(string trxFileName, Guid testId, string testName, bool isMstestAdapter) + private static void ValidateResultAttributesInTrx(string trxFileName, Guid testId, string testName, bool isMstestAdapter) { using FileStream file = File.OpenRead(trxFileName); using XmlReader reader = XmlReader.Create(file); @@ -956,7 +956,7 @@ private static Mock CreatePassTestResultEventArgsMock(strin private void MakeTestRunComplete() => MakeTestRunComplete(_testableTrxLogger); - private void MakeTestRunComplete(TestableTrxLogger testableTrxLogger) + private static void MakeTestRunComplete(TestableTrxLogger testableTrxLogger) { var pass = CreatePassTestResultEventArgsMock(); testableTrxLogger.TestResultHandler(new object(), pass.Object); diff --git a/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Utility/ConverterTests.cs b/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Utility/ConverterTests.cs index f9bc122e6c..63b56ad093 100644 --- a/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Utility/ConverterTests.cs +++ b/test/Microsoft.TestPlatform.Extensions.TrxLogger.UnitTests/Utility/ConverterTests.cs @@ -180,7 +180,7 @@ public void ToResultFilesShouldAddAttachmentsWithRelativeUri() testRun.RunConfiguration = new TestRunConfiguration("Testrun 1", _trxFileHelper); attachmentSets[0].Attachments.Add(uriDataAttachment1); - var resultFiles = _converter.ToResultFiles(attachmentSets, testRun, @"c:\temp", null); + var resultFiles = _converter.ToResultFiles(attachmentSets, testRun, @"c:\temp", null!); Assert.IsTrue(resultFiles[0].Contains("abc.txt")); }