diff --git a/Directory.Build.props b/Directory.Build.props
index c52560a235..10c3dd0e46 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -75,16 +75,6 @@
Microsoft.Testing.Platform
-
-
- true
-
- true
- true
- true
-
@@ -103,4 +93,14 @@
+
+
+ $(NoWarn);CS0436
+
+
+
+
+
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 200a555f01..77b88f4e70 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -58,7 +58,6 @@
-
diff --git a/eng/Polyfills.cs b/eng/Polyfills.cs
new file mode 100644
index 0000000000..fbddb3f60e
--- /dev/null
+++ b/eng/Polyfills.cs
@@ -0,0 +1,971 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+// This file provides polyfills for types that are not available on older target frameworks (netstandard2.0, .NET Framework).
+#pragma warning disable SA1201 // Elements should appear in the correct order
+#pragma warning disable SA1403 // File may only contain a single namespace
+#pragma warning disable SA1502 // Element should not be on a single line
+#pragma warning disable SA1649 // File name should match first type name
+#pragma warning disable SA1405 // Debug.Assert should provide message text
+#pragma warning disable SA1407 // Arithmetic expressions should declare precedence
+#pragma warning disable SA1513 // Closing brace should be followed by blank line
+#pragma warning disable SA1516 // Elements should be separated by blank line
+#pragma warning disable CA1305 // Specify IFormatProvider
+#pragma warning disable IDE0007 // Use 'var' instead of explicit type
+#pragma warning disable IDE0046 // If statement can be simplified
+#pragma warning disable IDE0065 // Misplaced using directive
+#pragma warning disable IDE0280 // Use 'nameof'
+#pragma warning disable SA1512 // Single-line comments should not be followed by blank line
+
+// On TFMs where IsExternalInit is provided by the BCL, add a TypeForwardedTo so that
+// assemblies compiled against the netstandard2.0 version (which had the polyfill type)
+// can resolve the type at runtime on net5+.
+// See https://github.com/SimonCropp/Polyfill/issues/290
+#if NET5_0_OR_GREATER
+#pragma warning disable RS0016 // Symbol is not part of the declared public API - compiler support type forwarding
+[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.IsExternalInit))]
+#pragma warning restore RS0016
+#else
+
+namespace System.Runtime.CompilerServices
+{
+ internal static class IsExternalInit;
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Module | global::System.AttributeTargets.Class | global::System.AttributeTargets.Struct | global::System.AttributeTargets.Constructor | global::System.AttributeTargets.Method | global::System.AttributeTargets.Property | global::System.AttributeTargets.Event | global::System.AttributeTargets.Interface, Inherited = false)]
+ internal sealed class RequiredMemberAttribute : Attribute { }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.All, AllowMultiple = true, Inherited = false)]
+ internal sealed class CompilerFeatureRequiredAttribute : Attribute
+ {
+ public CompilerFeatureRequiredAttribute(string featureName) => FeatureName = featureName;
+
+ public string FeatureName { get; }
+
+ public bool IsOptional { get; init; }
+ }
+}
+
+namespace System.Diagnostics.CodeAnalysis
+{
+ [global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false)]
+ internal sealed class DoesNotReturnAttribute : Attribute { }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Parameter, Inherited = false)]
+ internal sealed class DoesNotReturnIfAttribute : Attribute
+ {
+ public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue;
+
+ public bool ParameterValue { get; }
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Method | global::System.AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
+ internal sealed class MemberNotNullAttribute : Attribute
+ {
+ public MemberNotNullAttribute(string member) => Members = [member];
+
+ public MemberNotNullAttribute(params string[] members) => Members = members;
+
+ public string[] Members { get; }
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Method | global::System.AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
+ internal sealed class MemberNotNullWhenAttribute : Attribute
+ {
+ public MemberNotNullWhenAttribute(bool returnValue, string member)
+ {
+ ReturnValue = returnValue;
+ Members = [member];
+ }
+
+ public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
+ {
+ ReturnValue = returnValue;
+ Members = members;
+ }
+
+ public bool ReturnValue { get; }
+
+ public string[] Members { get; }
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Property | global::System.AttributeTargets.Parameter | global::System.AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
+ internal sealed class NotNullIfNotNullAttribute : Attribute
+ {
+ public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName;
+
+ public string ParameterName { get; }
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Parameter, Inherited = false)]
+ internal sealed class NotNullWhenAttribute : Attribute
+ {
+ public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
+
+ public bool ReturnValue { get; }
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Property | global::System.AttributeTargets.Field | global::System.AttributeTargets.Parameter | global::System.AttributeTargets.ReturnValue, Inherited = false)]
+ internal sealed class NotNullAttribute : Attribute { }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Property | global::System.AttributeTargets.Field | global::System.AttributeTargets.Parameter, Inherited = false)]
+ internal sealed class AllowNullAttribute : Attribute { }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Property | global::System.AttributeTargets.Field | global::System.AttributeTargets.Parameter, Inherited = false)]
+ internal sealed class DisallowNullAttribute : Attribute { }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Property | global::System.AttributeTargets.Field | global::System.AttributeTargets.Parameter | global::System.AttributeTargets.ReturnValue, Inherited = false)]
+ internal sealed class MaybeNullAttribute : Attribute { }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Parameter | global::System.AttributeTargets.Property | global::System.AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
+ internal sealed class StringSyntaxAttribute : Attribute
+ {
+ public const string Regex = nameof(Regex);
+ public const string Uri = nameof(Uri);
+ public const string Xml = nameof(Xml);
+
+ public StringSyntaxAttribute(string syntax, params object?[] arguments)
+ {
+ Syntax = syntax;
+ Arguments = arguments;
+ }
+
+ public string Syntax { get; }
+
+ public object?[] Arguments { get; }
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Field | global::System.AttributeTargets.ReturnValue | global::System.AttributeTargets.GenericParameter | global::System.AttributeTargets.Parameter | global::System.AttributeTargets.Property | global::System.AttributeTargets.Method | global::System.AttributeTargets.Class | global::System.AttributeTargets.Interface | global::System.AttributeTargets.Struct, Inherited = false)]
+ internal sealed class DynamicallyAccessedMembersAttribute : Attribute
+ {
+ public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) => MemberTypes = memberTypes;
+
+ public DynamicallyAccessedMemberTypes MemberTypes { get; }
+ }
+
+ [global::System.Flags]
+ internal enum DynamicallyAccessedMemberTypes
+ {
+ None = 0,
+ PublicParameterlessConstructor = 0x0001,
+ PublicConstructors = 0x0003,
+ NonPublicConstructors = 0x0004,
+ PublicMethods = 0x0008,
+ NonPublicMethods = 0x0010,
+ PublicFields = 0x0020,
+ NonPublicFields = 0x0040,
+ PublicNestedTypes = 0x0080,
+ NonPublicNestedTypes = 0x0100,
+ PublicProperties = 0x0200,
+ NonPublicProperties = 0x0400,
+ PublicEvents = 0x0800,
+ NonPublicEvents = 0x1000,
+ Interfaces = 0x2000,
+ All = ~None,
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Method | global::System.AttributeTargets.Constructor | global::System.AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
+ internal sealed class UnconditionalSuppressMessageAttribute : Attribute
+ {
+ public UnconditionalSuppressMessageAttribute(string category, string checkId)
+ {
+ Category = category;
+ CheckId = checkId;
+ }
+
+ public string Category { get; }
+
+ public string CheckId { get; }
+
+ public string? Scope { get; set; }
+
+ public string? Target { get; set; }
+
+ public string? MessageId { get; set; }
+
+ public string? Justification { get; set; }
+ }
+}
+
+namespace System.Runtime.Versioning
+{
+ [global::System.AttributeUsage(global::System.AttributeTargets.Assembly | global::System.AttributeTargets.Module | global::System.AttributeTargets.Class | global::System.AttributeTargets.Struct | global::System.AttributeTargets.Enum | global::System.AttributeTargets.Constructor | global::System.AttributeTargets.Method | global::System.AttributeTargets.Property | global::System.AttributeTargets.Field | global::System.AttributeTargets.Event | global::System.AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
+ internal sealed class SupportedOSPlatformAttribute : Attribute
+ {
+ public SupportedOSPlatformAttribute(string platformName) => PlatformName = platformName;
+
+ public string PlatformName { get; }
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Method | global::System.AttributeTargets.Property | global::System.AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
+ internal sealed class SupportedOSPlatformGuardAttribute : Attribute
+ {
+ public SupportedOSPlatformGuardAttribute(string platformName) => PlatformName = platformName;
+
+ public string PlatformName { get; }
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Assembly | global::System.AttributeTargets.Module | global::System.AttributeTargets.Class | global::System.AttributeTargets.Struct | global::System.AttributeTargets.Enum | global::System.AttributeTargets.Constructor | global::System.AttributeTargets.Method | global::System.AttributeTargets.Property | global::System.AttributeTargets.Field | global::System.AttributeTargets.Event | global::System.AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
+ internal sealed class UnsupportedOSPlatformAttribute : Attribute
+ {
+ public UnsupportedOSPlatformAttribute(string platformName) => PlatformName = platformName;
+
+ public string PlatformName { get; }
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Method | global::System.AttributeTargets.Property | global::System.AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
+ internal sealed class UnsupportedOSPlatformGuardAttribute : Attribute
+ {
+ public UnsupportedOSPlatformGuardAttribute(string platformName) => PlatformName = platformName;
+
+ public string PlatformName { get; }
+ }
+}
+
+#endif
+
+#if !NET6_0_OR_GREATER
+
+namespace System.Runtime.CompilerServices
+{
+ [global::System.AttributeUsage(global::System.AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+ internal sealed class CallerArgumentExpressionAttribute : Attribute
+ {
+ public CallerArgumentExpressionAttribute(string parameterName) => ParameterName = parameterName;
+
+ public string ParameterName { get; }
+ }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
+ internal sealed class InterpolatedStringHandlerAttribute : Attribute { }
+
+ [global::System.AttributeUsage(global::System.AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+ internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
+ {
+ public InterpolatedStringHandlerArgumentAttribute(string argument) => Arguments = [argument];
+
+ public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) => Arguments = arguments;
+
+ public string[] Arguments { get; }
+ }
+}
+
+namespace System.Diagnostics
+{
+ [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method | global::System.AttributeTargets.Constructor | global::System.AttributeTargets.Struct, Inherited = false)]
+ internal sealed class StackTraceHiddenAttribute : Attribute { }
+}
+namespace System.Runtime.CompilerServices
+{
+ [global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false)]
+ internal sealed class ModuleInitializerAttribute : Attribute { }
+}
+#endif
+
+#if !NET8_0_OR_GREATER
+
+namespace System.Diagnostics.CodeAnalysis
+{
+ [global::System.AttributeUsage(global::System.AttributeTargets.Assembly | global::System.AttributeTargets.Module | global::System.AttributeTargets.Class | global::System.AttributeTargets.Struct | global::System.AttributeTargets.Enum | global::System.AttributeTargets.Constructor | global::System.AttributeTargets.Method | global::System.AttributeTargets.Property | global::System.AttributeTargets.Field | global::System.AttributeTargets.Event | global::System.AttributeTargets.Interface | global::System.AttributeTargets.Delegate, Inherited = false)]
+ internal sealed class ExperimentalAttribute : Attribute
+ {
+ public ExperimentalAttribute(string diagnosticId) => DiagnosticId = diagnosticId;
+
+ public string DiagnosticId { get; }
+
+ public string? UrlFormat { get; set; }
+ }
+}
+
+#endif
+
+#if !NET9_0_OR_GREATER
+
+namespace System.Runtime.CompilerServices
+{
+ [global::System.AttributeUsage(global::System.AttributeTargets.Parameter, Inherited = false, AllowMultiple = false)]
+ internal sealed class ParamCollectionAttribute : Attribute { }
+}
+
+#endif
+
+#if !NET9_0_OR_GREATER
+
+namespace System.Threading
+{
+#pragma warning disable CS9216 // A value of type 'Lock' converted to a different type will use likely unintended monitor-based locking
+ internal sealed class Lock
+ {
+ public void Enter() => Monitor.Enter(this);
+
+ public void Exit() => Monitor.Exit(this);
+
+ public Scope EnterScope()
+ {
+ Monitor.Enter(this);
+ return new Scope(this);
+ }
+
+ public ref struct Scope
+ {
+ private Lock? _lock;
+
+ internal Scope(Lock @lock) => _lock = @lock;
+
+ public void Dispose()
+ {
+ Lock? lockObj = _lock;
+ if (lockObj is not null)
+ {
+ _lock = null;
+ lockObj.Exit();
+ }
+ }
+ }
+ }
+}
+
+#endif
+
+#if !NET5_0_OR_GREATER
+
+namespace System
+{
+ internal readonly struct Index : IEquatable
+ {
+ private readonly int _value;
+
+ public Index(int value, bool fromEnd = false)
+ {
+ if (value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), "Index must not be negative.");
+ }
+
+ _value = fromEnd ? ~value : value;
+ }
+
+ private Index(int value) => _value = value;
+
+ public static Index Start => new(0);
+
+ public static Index End => new(~0);
+
+ public int Value => _value < 0 ? ~_value : _value;
+
+ public bool IsFromEnd => _value < 0;
+
+ public static Index FromStart(int value) => value >= 0 ? new Index(value) : throw new ArgumentOutOfRangeException(nameof(value), "Index must not be negative.");
+
+ public static Index FromEnd(int value) => value >= 0 ? new Index(~value) : throw new ArgumentOutOfRangeException(nameof(value), "Index must not be negative.");
+
+ public static implicit operator Index(int value) => FromStart(value);
+
+ public int GetOffset(int length)
+ {
+ int offset = _value;
+ if (IsFromEnd)
+ {
+ offset += length + 1;
+ }
+
+ return offset;
+ }
+
+ public override bool Equals(object? value) => value is Index index && _value == index._value;
+
+ public bool Equals(Index other) => _value == other._value;
+
+ public override int GetHashCode() => _value;
+
+ public override string ToString() => IsFromEnd ? $"^{(uint)Value}" : ((uint)Value).ToString();
+ }
+
+ internal readonly struct Range : IEquatable
+ {
+ public Index Start { get; }
+
+ public Index End { get; }
+
+ public Range(Index start, Index end)
+ {
+ Start = start;
+ End = end;
+ }
+
+ public static Range StartAt(Index start) => new(start, Index.End);
+
+ public static Range EndAt(Index end) => new(Index.Start, end);
+
+ public static Range All => new(Index.Start, Index.End);
+
+ public override bool Equals(object? value) => value is Range r && r.Start.Equals(Start) && r.End.Equals(End);
+
+ public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End);
+
+ public override int GetHashCode() => Start.GetHashCode() * 31 + End.GetHashCode();
+
+ public override string ToString() => $"{Start}..{End}";
+
+ public void GetOffsetAndLength(int length, out int offset, out int len)
+ {
+ int start = Start.GetOffset(length);
+ int end = End.GetOffset(length);
+ if ((uint)end > (uint)length || (uint)start > (uint)end)
+ {
+ throw new ArgumentOutOfRangeException(nameof(length));
+ }
+
+ offset = start;
+ len = end - start;
+ }
+ }
+}
+
+namespace System.Runtime.CompilerServices
+{
+ internal static class RuntimeHelpers
+ {
+ /// Slices the specified array using the specified range.
+ /// The type of the array elements.
+ public static T[] GetSubArray(T[] array, Range range)
+ {
+ range.GetOffsetAndLength(array.Length, out int offset, out int length);
+ T[] dest = new T[length];
+ Array.Copy(array, offset, dest, 0, length);
+ return dest;
+ }
+ }
+}
+
+#endif
+
+namespace Microsoft.CodeAnalysis
+{
+ [global::System.AttributeUsage(global::System.AttributeTargets.All, AllowMultiple = false, Inherited = false)]
+ internal sealed partial class EmbeddedAttribute : global::System.Attribute { }
+}
+
+#pragma warning disable CS8603 // Possible null reference return
+#pragma warning disable CS8777 // Parameter must have a non-null value when exiting
+#pragma warning disable RS0030 // Banned API - Ensure is the guard implementation itself
+internal static class Ensure
+{
+ [return: global::System.Diagnostics.CodeAnalysis.NotNull]
+ public static T NotNull([global::System.Diagnostics.CodeAnalysis.NotNull] T? argument, [global::System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? paramName = null)
+ {
+ if (argument is null)
+ {
+ throw new global::System.ArgumentNullException(paramName);
+ }
+
+ return argument;
+ }
+
+ public static string NotNullOrEmpty([global::System.Diagnostics.CodeAnalysis.NotNull] string? argument, [global::System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? paramName = null)
+ {
+ if (argument is null)
+ {
+ throw new global::System.ArgumentNullException(paramName);
+ }
+
+ if (argument.Length == 0)
+ {
+ throw new global::System.ArgumentException("Value cannot be null or empty.", paramName);
+ }
+
+ return argument;
+ }
+
+ public static void NotNullOrEmpty([global::System.Diagnostics.CodeAnalysis.NotNull] global::System.Collections.Generic.IEnumerable? argument, [global::System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? paramName = null)
+ {
+ if (argument is null)
+ {
+ throw new global::System.ArgumentNullException(paramName);
+ }
+
+ if (argument is global::System.Collections.Generic.ICollection collection)
+ {
+ if (collection.Count == 0)
+ {
+ throw new global::System.ArgumentException("Value cannot be empty.", paramName);
+ }
+
+ return;
+ }
+
+ using global::System.Collections.Generic.IEnumerator enumerator = argument.GetEnumerator();
+ if (!enumerator.MoveNext())
+ {
+ throw new global::System.ArgumentException("Value cannot be empty.", paramName);
+ }
+ }
+
+ public static string NotNullOrWhiteSpace([global::System.Diagnostics.CodeAnalysis.NotNull] string? argument, [global::System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? paramName = null)
+ {
+ if (argument is null)
+ {
+ throw new global::System.ArgumentNullException(paramName);
+ }
+
+ if (argument.Trim().Length == 0)
+ {
+ throw new global::System.ArgumentException("Value cannot be null or whitespace.", paramName);
+ }
+
+ return argument;
+ }
+}
+
+// Backward-compatible stubs for Polyfills.Guard and Polyfills.Ensure types.
+// The old Polyfill NuGet package generated these types into the Microsoft.Testing.Platform assembly;
+// old extension packages (compiled against the previous platform version with InternalsVisibleTo)
+// may reference these types at runtime. Providing them here prevents TypeLoadExceptions.
+#if IS_CORE_MTP
+namespace Polyfills
+{
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.Diagnostics.DebuggerNonUserCode]
+ internal static class Guard
+ {
+ [return: global::System.Diagnostics.CodeAnalysis.NotNull]
+ public static T NotNull([global::System.Diagnostics.CodeAnalysis.NotNull] T? argument, [global::System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? name = null)
+ where T : class
+ {
+ if (argument is null)
+ {
+ throw new global::System.ArgumentNullException(name);
+ }
+
+ return argument;
+ }
+
+ [return: global::System.Diagnostics.CodeAnalysis.NotNull]
+ public static string NotNull([global::System.Diagnostics.CodeAnalysis.NotNull] string? argument, [global::System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? name = null)
+ {
+ if (argument is null)
+ {
+ throw new global::System.ArgumentNullException(name);
+ }
+
+ return argument;
+ }
+
+ public static string NotNullOrEmpty([global::System.Diagnostics.CodeAnalysis.NotNull] string? value, [global::System.Runtime.CompilerServices.CallerArgumentExpression("value")] string? name = null)
+ => Ensure.NotNullOrEmpty(value, name);
+
+ public static T NotNullOrEmpty([global::System.Diagnostics.CodeAnalysis.NotNull] T? value, [global::System.Runtime.CompilerServices.CallerArgumentExpression("value")] string? name = null)
+ where T : global::System.Collections.IEnumerable
+ => Ensure.NotNullOrEmpty(value, name);
+
+ public static string NotNullOrWhiteSpace([global::System.Diagnostics.CodeAnalysis.NotNull] string? value, [global::System.Runtime.CompilerServices.CallerArgumentExpression("value")] string? name = null)
+ => Ensure.NotNullOrWhiteSpace(value, name);
+
+ public static void FileExists(string path, [global::System.Runtime.CompilerServices.CallerArgumentExpression("path")] string? name = null)
+ => Ensure.FileExists(path, name);
+
+ public static void DirectoryExists(string path, [global::System.Runtime.CompilerServices.CallerArgumentExpression("path")] string? name = null)
+ => Ensure.DirectoryExists(path, name);
+ }
+
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.Diagnostics.DebuggerNonUserCode]
+ internal static class Ensure
+ {
+ [return: global::System.Diagnostics.CodeAnalysis.NotNull]
+ public static T NotNull([global::System.Diagnostics.CodeAnalysis.NotNull] T? argument, [global::System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? name = null)
+ where T : class
+ {
+ if (argument is null)
+ {
+ throw new global::System.ArgumentNullException(name);
+ }
+
+ return argument;
+ }
+
+ [return: global::System.Diagnostics.CodeAnalysis.NotNull]
+ public static string NotNull([global::System.Diagnostics.CodeAnalysis.NotNull] string? argument, [global::System.Runtime.CompilerServices.CallerArgumentExpression("argument")] string? name = null)
+ {
+ if (argument is null)
+ {
+ throw new global::System.ArgumentNullException(name);
+ }
+
+ return argument;
+ }
+
+ public static string NotNullOrEmpty([global::System.Diagnostics.CodeAnalysis.NotNull] string? value, [global::System.Runtime.CompilerServices.CallerArgumentExpression("value")] string? name = null)
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ throw new global::System.ArgumentException("Must not be null or empty.", name);
+ }
+
+ return value;
+ }
+
+ [return: global::System.Diagnostics.CodeAnalysis.NotNull]
+ public static T NotNullOrEmpty([global::System.Diagnostics.CodeAnalysis.NotNull] T? value, [global::System.Runtime.CompilerServices.CallerArgumentExpression("value")] string? name = null)
+ where T : global::System.Collections.IEnumerable
+ {
+ if (value is null)
+ {
+ throw new global::System.ArgumentNullException(name);
+ }
+
+ global::System.Collections.IEnumerator enumerator = value.GetEnumerator();
+ try
+ {
+ if (!enumerator.MoveNext())
+ {
+ throw new global::System.ArgumentException("Must not be empty.", name);
+ }
+ }
+ finally
+ {
+ (enumerator as global::System.IDisposable)?.Dispose();
+ }
+
+ return value;
+ }
+
+ public static string NotNullOrWhiteSpace([global::System.Diagnostics.CodeAnalysis.NotNull] string? value, [global::System.Runtime.CompilerServices.CallerArgumentExpression("value")] string? name = null)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ throw new global::System.ArgumentException("Must not be null or whitespace.", name);
+ }
+
+ return value;
+ }
+
+ public static void FileExists(string path, [global::System.Runtime.CompilerServices.CallerArgumentExpression("path")] string? name = null)
+ {
+ if (!global::System.IO.File.Exists(path))
+ {
+ throw new global::System.ArgumentException($"File not found. Path: {path}", name);
+ }
+ }
+
+ public static void DirectoryExists(string path, [global::System.Runtime.CompilerServices.CallerArgumentExpression("path")] string? name = null)
+ {
+ if (!global::System.IO.Directory.Exists(path))
+ {
+ throw new global::System.ArgumentException($"Directory not found. Path: {path}", name);
+ }
+ }
+ }
+
+ // Polyfills.Polyfill stub: The old Polyfill NuGet package generated this type into every assembly.
+ // Old extensions (compiled with InternalsVisibleTo to the platform) may reference methods on
+ // this type from the platform assembly. We need to provide it for backward compatibility.
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ [global::System.Diagnostics.DebuggerNonUserCode]
+ internal static class Polyfill
+ {
+#if NETCOREAPP
+ public static bool Contains(global::System.ReadOnlySpan span, T value, global::System.Collections.Generic.IEqualityComparer? comparer = null)
+ {
+ comparer ??= global::System.Collections.Generic.EqualityComparer.Default;
+ foreach (T item in span)
+ {
+ if (comparer.Equals(item, value))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+#endif
+ }
+}
+#endif
+
+// All extension method polyfills are guarded with IS_CORE_MTP to avoid ambiguity when
+// projects reference Microsoft.Testing.Platform with InternalsVisibleTo. Projects that
+// do not reference Platform and need these extensions should provide their own copies.
+#if IS_CORE_MTP
+
+#if !NET8_0_OR_GREATER
+
+internal static class CancellationTokenSourceExtensions
+{
+ public static global::System.Threading.Tasks.Task CancelAsync(this global::System.Threading.CancellationTokenSource cancellationTokenSource)
+ {
+ cancellationTokenSource.Cancel();
+ return global::System.Threading.Tasks.Task.CompletedTask;
+ }
+}
+
+#endif // !NET8_0_OR_GREATER
+
+#if !NET5_0_OR_GREATER
+
+internal static class PolyfillStringExtensions
+{
+ public static bool Contains(this string s, char c) => s.IndexOf(c) >= 0;
+
+ public static bool StartsWith(this string s, char c) => s.Length > 0 && s[0] == c;
+
+ public static bool EndsWith(this string s, char c) => s.Length > 0 && s[s.Length - 1] == c;
+
+ public static string[] Split(this string s, char separator, global::System.StringSplitOptions options = global::System.StringSplitOptions.None) =>
+ s.Split([separator], options);
+
+ public static string[] Split(this string s, char separator, int count, global::System.StringSplitOptions options = global::System.StringSplitOptions.None) =>
+ s.Split([separator], count, options);
+
+ public static string Replace(this string s, string oldValue, string? newValue, global::System.StringComparison comparisonType)
+ {
+ if (comparisonType == global::System.StringComparison.Ordinal)
+ {
+ return s.Replace(oldValue, newValue);
+ }
+
+ var sb = new global::System.Text.StringBuilder();
+ int previousIndex = 0;
+ int index = s.IndexOf(oldValue, comparisonType);
+ while (index != -1)
+ {
+ sb.Append(s, previousIndex, index - previousIndex);
+ sb.Append(newValue);
+ index += oldValue.Length;
+ previousIndex = index;
+ index = s.IndexOf(oldValue, index, comparisonType);
+ }
+
+ sb.Append(s, previousIndex, s.Length - previousIndex);
+ return sb.ToString();
+ }
+
+ public static bool Contains(this string s, string value, global::System.StringComparison comparisonType) =>
+ s.IndexOf(value, comparisonType) >= 0;
+
+ public static int GetHashCode(this string s, global::System.StringComparison comparisonType) =>
+ comparisonType switch
+ {
+ global::System.StringComparison.Ordinal => global::System.StringComparer.Ordinal.GetHashCode(s),
+ global::System.StringComparison.OrdinalIgnoreCase => global::System.StringComparer.OrdinalIgnoreCase.GetHashCode(s),
+ _ => global::System.StringComparer.OrdinalIgnoreCase.GetHashCode(s),
+ };
+}
+
+internal static class PolyfillEnumExtensions
+{
+ public static TEnum Parse(string value)
+ where TEnum : struct =>
+ (TEnum)global::System.Enum.Parse(typeof(TEnum), value);
+
+ public static TEnum Parse(string value, bool ignoreCase)
+ where TEnum : struct =>
+ (TEnum)global::System.Enum.Parse(typeof(TEnum), value, ignoreCase);
+}
+
+// Note: Deconstruct for KeyValuePair is intentionally NOT provided here because it causes
+// ambiguity errors when projects reference each other with InternalsVisibleTo and both
+// compile this file. It is provided in Microsoft.Testing.Platform project's own source.
+
+internal static class PolyfillDictionaryExtensions
+{
+ public static bool TryAdd(this global::System.Collections.Generic.Dictionary dictionary, TKey key, TValue value)
+ where TKey : notnull
+ {
+ if (!dictionary.ContainsKey(key))
+ {
+ dictionary.Add(key, value);
+ return true;
+ }
+
+ return false;
+ }
+}
+
+internal static class PolyfillStringBuilderExtensions
+{
+ public static global::System.Text.StringBuilder AppendJoin(this global::System.Text.StringBuilder sb, string separator, global::System.Collections.Generic.IEnumerable values)
+ {
+ bool first = true;
+ foreach (string value in values)
+ {
+ if (!first)
+ {
+ sb.Append(separator);
+ }
+
+ sb.Append(value);
+ first = false;
+ }
+
+ return sb;
+ }
+
+ public static global::System.Text.StringBuilder AppendJoin(this global::System.Text.StringBuilder sb, string separator, global::System.Collections.Generic.IEnumerable values)
+ {
+ bool first = true;
+ foreach (T value in values)
+ {
+ if (!first)
+ {
+ sb.Append(separator);
+ }
+
+ sb.Append(value);
+ first = false;
+ }
+
+ return sb;
+ }
+
+ public static global::System.Text.StringBuilder AppendJoin(this global::System.Text.StringBuilder sb, char separator, global::System.Collections.Generic.IEnumerable values) =>
+ sb.AppendJoin(separator.ToString(), values);
+}
+
+internal static class PolyfillTaskExtensions
+{
+ public static async global::System.Threading.Tasks.Task WaitAsync(this global::System.Threading.Tasks.Task task, global::System.Threading.CancellationToken cancellationToken)
+ {
+ var tcs = new global::System.Threading.Tasks.TaskCompletionSource(global::System.Threading.Tasks.TaskCreationOptions.RunContinuationsAsynchronously);
+ using (cancellationToken.Register(s => ((global::System.Threading.Tasks.TaskCompletionSource)s!).TrySetCanceled(cancellationToken), tcs))
+ {
+ if (task != await global::System.Threading.Tasks.Task.WhenAny(task, tcs.Task).ConfigureAwait(false))
+ {
+ throw new global::System.OperationCanceledException(cancellationToken);
+ }
+ }
+
+ await task.ConfigureAwait(false);
+ }
+
+ public static async global::System.Threading.Tasks.Task WaitAsync(this global::System.Threading.Tasks.Task task, global::System.TimeSpan timeout, global::System.Threading.CancellationToken cancellationToken = default)
+ {
+ using var cts = global::System.Threading.CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
+ cts.CancelAfter(timeout);
+ try
+ {
+ await task.WaitAsync(cts.Token).ConfigureAwait(false);
+ }
+ catch (global::System.OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
+ {
+ throw new global::System.TimeoutException();
+ }
+ }
+
+ public static async global::System.Threading.Tasks.Task WaitAsync(this global::System.Threading.Tasks.Task task, global::System.Threading.CancellationToken cancellationToken)
+ {
+ var tcs = new global::System.Threading.Tasks.TaskCompletionSource(global::System.Threading.Tasks.TaskCreationOptions.RunContinuationsAsynchronously);
+ using (cancellationToken.Register(s => ((global::System.Threading.Tasks.TaskCompletionSource)s!).TrySetCanceled(cancellationToken), tcs))
+ {
+ if (task != await global::System.Threading.Tasks.Task.WhenAny(task, tcs.Task).ConfigureAwait(false))
+ {
+ throw new global::System.OperationCanceledException(cancellationToken);
+ }
+ }
+
+ return await task.ConfigureAwait(false);
+ }
+}
+
+internal static class PolyfillProcessExtensions
+{
+ public static global::System.Threading.Tasks.Task WaitForExitAsync(this global::System.Diagnostics.Process process, global::System.Threading.CancellationToken cancellationToken = default)
+ {
+ if (process.HasExited)
+ {
+ return global::System.Threading.Tasks.Task.CompletedTask;
+ }
+
+ var tcs = new global::System.Threading.Tasks.TaskCompletionSource(global::System.Threading.Tasks.TaskCreationOptions.RunContinuationsAsynchronously);
+ process.EnableRaisingEvents = true;
+
+ global::System.EventHandler handler = (_, _) => tcs.TrySetResult(true);
+ process.Exited += handler;
+
+ global::System.Threading.CancellationTokenRegistration cancellationRegistration = default;
+ if (cancellationToken.CanBeCanceled)
+ {
+ cancellationRegistration = cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken));
+ }
+
+ if (process.HasExited)
+ {
+ process.Exited -= handler;
+ cancellationRegistration.Dispose();
+ return global::System.Threading.Tasks.Task.CompletedTask;
+ }
+
+ return tcs.Task.ContinueWith(
+ _ =>
+ {
+ process.Exited -= handler;
+ cancellationRegistration.Dispose();
+ },
+ global::System.Threading.CancellationToken.None,
+ global::System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously,
+ global::System.Threading.Tasks.TaskScheduler.Default);
+ }
+
+ public static void Kill(this global::System.Diagnostics.Process process, bool entireProcessTree) =>
+ // entireProcessTree not supported on netstandard2.0 - just kill the process
+ process.Kill();
+}
+
+#endif // !NET5_0_OR_GREATER
+
+#endif // IS_CORE_MTP
+
+#if !NET5_0_OR_GREATER
+
+internal static class OperatingSystem
+{
+ public static bool IsBrowser() => false;
+
+ public static bool IsWasi() => false;
+
+ public static bool IsAndroid() => false;
+
+ public static bool IsIOS() => false;
+
+ public static bool IsTvOS() => false;
+
+#if NETFRAMEWORK
+ public static bool IsWindows() => global::System.Environment.OSVersion.Platform == global::System.PlatformID.Win32NT;
+
+ public static bool IsLinux() => false;
+
+ public static bool IsMacOS() => false;
+#else
+ public static bool IsWindows() => global::System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(global::System.Runtime.InteropServices.OSPlatform.Windows);
+
+ public static bool IsLinux() => global::System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(global::System.Runtime.InteropServices.OSPlatform.Linux);
+
+ public static bool IsMacOS() => global::System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(global::System.Runtime.InteropServices.OSPlatform.OSX);
+#endif
+}
+
+#endif
+
+#if !NET7_0_OR_GREATER
+
+namespace System.Diagnostics
+{
+ internal sealed class UnreachableException : Exception
+ {
+ public UnreachableException()
+ : base("The program executed an instruction that was thought to be unreachable.")
+ {
+ }
+
+ public UnreachableException(string? message)
+ : base(message)
+ {
+ }
+
+ public UnreachableException(string? message, Exception? innerException)
+ : base(message, innerException)
+ {
+ }
+ }
+}
+
+#endif
diff --git a/src/Adapter/MSTest.Engine/MSTest.Engine.csproj b/src/Adapter/MSTest.Engine/MSTest.Engine.csproj
index d9d5992e1e..d995eb4dd5 100644
--- a/src/Adapter/MSTest.Engine/MSTest.Engine.csproj
+++ b/src/Adapter/MSTest.Engine/MSTest.Engine.csproj
@@ -59,10 +59,6 @@ This package provides a new experimental engine for MSTest test framework.]]>
-
-
-
-
diff --git a/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.csproj b/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.csproj
index b6d063c7d2..e2c8fd7767 100644
--- a/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.csproj
+++ b/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.csproj
@@ -65,10 +65,6 @@
-
-
-
-
@@ -90,7 +86,6 @@
-
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Execution/Polyfills/EmbeddedAttribute.cs b/src/Adapter/MSTestAdapter.PlatformServices/Execution/Polyfills/EmbeddedAttribute.cs
index 2665ce0bb4..b3c7f40add 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/Execution/Polyfills/EmbeddedAttribute.cs
+++ b/src/Adapter/MSTestAdapter.PlatformServices/Execution/Polyfills/EmbeddedAttribute.cs
@@ -1,10 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-#if NETFRAMEWORK
-namespace Microsoft.CodeAnalysis;
-
-internal sealed partial class EmbeddedAttribute : Attribute
-{
-}
-#endif
+// EmbeddedAttribute is now provided by eng/Polyfills.cs.
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.cs b/src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.cs
index 933ab3a2f3..e5073fcb0b 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.cs
+++ b/src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.cs
@@ -199,7 +199,11 @@ private static bool IsValueTask(this MethodInfo method)
private static void InferGenerics(Type parameterType, Type argumentType, List<(Type ParameterType, Type Substitution)> result)
{
- if (parameterType.IsGenericMethodParameter())
+#if NET5_0_OR_GREATER
+ if (parameterType.IsGenericMethodParameter)
+#else
+ if (parameterType.IsGenericParameter && parameterType.DeclaringMethod is not null)
+#endif
{
// We found a generic parameter. The argument type should be the substitution for it.
result.Add((parameterType, argumentType));
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/MSTestAdapter.PlatformServices.csproj b/src/Adapter/MSTestAdapter.PlatformServices/MSTestAdapter.PlatformServices.csproj
index 3393d8818c..3b6cac444f 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/MSTestAdapter.PlatformServices.csproj
+++ b/src/Adapter/MSTestAdapter.PlatformServices/MSTestAdapter.PlatformServices.csproj
@@ -35,7 +35,6 @@
-
@@ -55,7 +54,6 @@
-
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/MSTestSettings.cs b/src/Adapter/MSTestAdapter.PlatformServices/MSTestSettings.cs
index 501d5559cd..26b3d84634 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/MSTestSettings.cs
+++ b/src/Adapter/MSTestAdapter.PlatformServices/MSTestSettings.cs
@@ -713,7 +713,7 @@ private static void SetParallelSettings(XmlReader reader, MSTestSettings setting
CultureInfo.CurrentCulture,
Resource.InvalidParallelScopeValue,
value,
- string.Join(", ", Enum.GetNames())));
+ string.Join(", ", Enum.GetNames(typeof(ExecutionScope)))));
break;
}
@@ -740,7 +740,7 @@ private static void SetParallelSettings(XmlReader reader, MSTestSettings setting
private static bool TryParseEnum(string value, out T result)
where T : struct, Enum
=> Enum.TryParse(value, true, out result)
- && Enum.IsDefined(result);
+ && Enum.IsDefined(typeof(T), result);
private static void SetGlobalSettings(
[StringSyntax(StringSyntaxAttribute.Xml, nameof(runsettingsXml))] string runsettingsXml,
@@ -902,7 +902,7 @@ internal static void SetSettingsFromConfig(IConfiguration configuration, IMessag
CultureInfo.CurrentCulture,
Resource.InvalidParallelScopeValue,
value,
- string.Join(", ", Enum.GetNames())));
+ string.Join(", ", Enum.GetNames(typeof(ExecutionScope)))));
}
settings.ParallelizationScope = scope;
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/PolyfillExtensions.cs b/src/Adapter/MSTestAdapter.PlatformServices/PolyfillExtensions.cs
new file mode 100644
index 0000000000..59eff40e52
--- /dev/null
+++ b/src/Adapter/MSTestAdapter.PlatformServices/PolyfillExtensions.cs
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+// Polyfill extension methods for the Adapter projects which target
+// net462 and need APIs not available on .NET Framework.
+#if !NET5_0_OR_GREATER
+
+internal static class AdapterPolyfillExtensions
+{
+ public static bool Contains(this string s, char c) => s.IndexOf(c) >= 0;
+
+ public static bool StartsWith(this string s, char c) => s.Length > 0 && s[0] == c;
+
+ public static bool EndsWith(this string s, char c) => s.Length > 0 && s[s.Length - 1] == c;
+
+ public static bool IsAssignableTo(this System.Type type, System.Type? targetType)
+ => targetType?.IsAssignableFrom(type) ?? false;
+
+ public static bool TryAdd(this System.Collections.Generic.Dictionary dictionary, TKey key, TValue value)
+ where TKey : notnull
+ {
+ if (!dictionary.ContainsKey(key))
+ {
+ dictionary.Add(key, value);
+ return true;
+ }
+
+ return false;
+ }
+
+ public static System.Text.StringBuilder AppendJoin(this System.Text.StringBuilder sb, string separator, System.Collections.Generic.IEnumerable values)
+ {
+ bool first = true;
+ foreach (string value in values)
+ {
+ if (!first)
+ {
+ sb.Append(separator);
+ }
+
+ sb.Append(value);
+ first = false;
+ }
+
+ return sb;
+ }
+
+ public static System.Text.StringBuilder AppendJoin(this System.Text.StringBuilder sb, char separator, System.Collections.Generic.IEnumerable values) =>
+ sb.AppendJoin(separator.ToString(), values);
+
+ public static TValue GetOrAdd(this System.Collections.Concurrent.ConcurrentDictionary dictionary, TKey key, System.Func valueFactory, TArg factoryArgument)
+ where TKey : notnull
+ => dictionary.GetOrAdd(key, k => valueFactory(k, factoryArgument));
+
+ public static string[] Split(this string s, char separator, System.StringSplitOptions options) =>
+ s.Split([separator], options);
+}
+
+#endif
+
+#if !NET8_0_OR_GREATER
+
+internal static class AdapterCancellationTokenSourcePolyfill
+{
+ public static System.Threading.Tasks.Task CancelAsync(this System.Threading.CancellationTokenSource cts)
+ {
+ cts.Cancel();
+ return System.Threading.Tasks.Task.CompletedTask;
+ }
+}
+
+#endif
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Services/TestDataSource.cs b/src/Adapter/MSTestAdapter.PlatformServices/Services/TestDataSource.cs
index 2fea97032a..db8fd73992 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/Services/TestDataSource.cs
+++ b/src/Adapter/MSTestAdapter.PlatformServices/Services/TestDataSource.cs
@@ -142,7 +142,7 @@ private static void GetConnectionProperties(DataSourceAttribute dataSourceAttrib
providerNameInvariant = ConfigurationManager.ConnectionStrings[element.ConnectionString].ProviderName;
connectionString = ConfigurationManager.ConnectionStrings[element.ConnectionString].ConnectionString;
tableName = element.DataTableName;
- dataAccessMethod = Enum.Parse(element.DataAccessMethod);
+ dataAccessMethod = (DataAccessMethod)Enum.Parse(typeof(DataAccessMethod), element.DataAccessMethod);
}
#endif
}
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.cs b/src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.cs
index a36cdb5b98..feedd430c8 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.cs
+++ b/src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.cs
@@ -136,7 +136,7 @@ public void SetupHost()
if (PlatformServiceProvider.Instance.AdapterTraceLogger.IsInfoEnabled)
{
- PlatformServiceProvider.Instance.AdapterTraceLogger.Info("DesktopTestSourceHost.SetupHost(): Creating assembly resolver with resolution paths {0}.", string.Join(',', resolutionPaths));
+ PlatformServiceProvider.Instance.AdapterTraceLogger.Info("DesktopTestSourceHost.SetupHost(): Creating assembly resolver with resolution paths {0}.", string.Join(",", resolutionPaths));
}
// NOTE: These 2 lines are super important, see https://github.com/microsoft/testfx/issues/2922
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtility.cs b/src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtility.cs
index 00aaac90be..1003d3ad9d 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtility.cs
+++ b/src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtility.cs
@@ -64,7 +64,8 @@ public override void AddDeploymentItemsBasedOnMsTestSetting(string testSourceHan
/// Root deployment directory.
public override string GetRootDeploymentDirectory(string baseDirectory)
{
- string dateTimeSuffix = $"{DateTime.Now.ToString("yyyyMMddTHHmmss", DateTimeFormatInfo.InvariantInfo)}_{Environment.ProcessId}";
+ using var currentProcess = Process.GetCurrentProcess();
+ string dateTimeSuffix = $"{DateTime.Now.ToString("yyyyMMddTHHmmss", DateTimeFormatInfo.InvariantInfo)}_{currentProcess.Id}";
string directoryName = string.Format(CultureInfo.InvariantCulture, Resource.TestRunName, DeploymentFolderPrefix,
#if NETFRAMEWORK
Environment.UserName,
diff --git a/src/Analyzers/MSTest.Analyzers.CodeFixes/MSTest.Analyzers.CodeFixes.csproj b/src/Analyzers/MSTest.Analyzers.CodeFixes/MSTest.Analyzers.CodeFixes.csproj
index ad9bdcf545..525d079c19 100644
--- a/src/Analyzers/MSTest.Analyzers.CodeFixes/MSTest.Analyzers.CodeFixes.csproj
+++ b/src/Analyzers/MSTest.Analyzers.CodeFixes/MSTest.Analyzers.CodeFixes.csproj
@@ -8,7 +8,6 @@
-
diff --git a/src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj b/src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
index 77efce2f98..cc4f02058b 100644
--- a/src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
+++ b/src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
@@ -20,7 +20,6 @@
-
diff --git a/src/Analyzers/MSTest.Analyzers/RoslynAnalyzerHelpers/AnalyzerPolyfillExtensions.cs b/src/Analyzers/MSTest.Analyzers/RoslynAnalyzerHelpers/AnalyzerPolyfillExtensions.cs
new file mode 100644
index 0000000000..d1145b8dc1
--- /dev/null
+++ b/src/Analyzers/MSTest.Analyzers/RoslynAnalyzerHelpers/AnalyzerPolyfillExtensions.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+// Polyfill extension methods specific to the Analyzers project (which targets netstandard2.0
+// only and does not reference Microsoft.Testing.Platform).
+
+internal static class AnalyzerPolyfillExtensions
+{
+ public static bool IsAssignableTo(this System.Type type, System.Type? targetType)
+ => targetType?.IsAssignableFrom(type) ?? false;
+
+ public static void Deconstruct(this System.Collections.Generic.KeyValuePair pair, out TKey key, out TValue value)
+ {
+ key = pair.Key;
+ value = pair.Value;
+ }
+
+ public static TValue GetValueOrDefault(this System.Collections.Generic.IDictionary dictionary, TKey key, TValue defaultValue)
+ where TKey : notnull
+ => dictionary.TryGetValue(key, out TValue? value) ? value : defaultValue;
+
+ public static TValue GetValueOrDefault(this System.Collections.Immutable.IImmutableDictionary dictionary, TKey key, TValue defaultValue)
+ where TKey : notnull
+ => dictionary.TryGetValue(key, out TValue? value) ? value : defaultValue;
+
+ public static bool Contains(this string s, char c) => s.IndexOf(c) >= 0;
+
+ public static bool StartsWith(this string s, char c) => s.Length > 0 && s[0] == c;
+
+ public static bool EndsWith(this string s, char c) => s.Length > 0 && s[s.Length - 1] == c;
+}
diff --git a/src/Analyzers/MSTest.SourceGeneration/Helpers/SystemPolyfills.cs b/src/Analyzers/MSTest.SourceGeneration/Helpers/SystemPolyfills.cs
index 6a80a1ca13..ec5303962d 100644
--- a/src/Analyzers/MSTest.SourceGeneration/Helpers/SystemPolyfills.cs
+++ b/src/Analyzers/MSTest.SourceGeneration/Helpers/SystemPolyfills.cs
@@ -1,36 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under dual-license. See LICENSE.PLATFORMTOOLS.txt file in the project root for full license information.
-#if !NETCOREAPP
-#pragma warning disable SA1403 // File may only contain a single namespace
-#pragma warning disable SA1642 // Constructor summary documentation should begin with standard text
-#pragma warning disable SA1623 // Property summary documentation should match accessors
-
-using System.ComponentModel;
-
-namespace System.Runtime.CompilerServices
-{
- [EditorBrowsable(EditorBrowsableState.Never)]
- internal static class IsExternalInit;
-}
-
-// This was copied from https://github.com/dotnet/coreclr/blob/60f1e6265bd1039f023a82e0643b524d6aaf7845/src/System.Private.CoreLib/shared/System/Diagnostics/CodeAnalysis/NullableAttributes.cs
-// and updated to have the scope of the attributes be internal.
-namespace System.Diagnostics.CodeAnalysis
-{
- /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it.
- [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
- internal sealed class NotNullWhenAttribute : Attribute
- {
- /// Initializes the attribute with the specified return value condition.
- ///
- /// The return value condition. If the method returns this value, the associated parameter will not be null.
- ///
- public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
-
- /// Gets the return value condition.
- public bool ReturnValue { get; }
- }
-}
-
-#endif
+// Polyfills for IsExternalInit and NotNullWhenAttribute are provided by eng/Polyfills.cs.
+// This file is kept for reference but no longer defines those types.
diff --git a/src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Microsoft.Testing.Extensions.AzureDevOpsReport.csproj b/src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Microsoft.Testing.Extensions.AzureDevOpsReport.csproj
index 9c467429e1..dbd6a9a032 100644
--- a/src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Microsoft.Testing.Extensions.AzureDevOpsReport.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Microsoft.Testing.Extensions.AzureDevOpsReport.csproj
@@ -44,10 +44,6 @@ This package extends Microsoft Testing Platform to provide a Azure DevOps report
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.AzureFoundry/Microsoft.Testing.Extensions.AzureFoundry.csproj b/src/Platform/Microsoft.Testing.Extensions.AzureFoundry/Microsoft.Testing.Extensions.AzureFoundry.csproj
index 93bcbdbb9f..a278941d93 100644
--- a/src/Platform/Microsoft.Testing.Extensions.AzureFoundry/Microsoft.Testing.Extensions.AzureFoundry.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.AzureFoundry/Microsoft.Testing.Extensions.AzureFoundry.csproj
@@ -31,7 +31,6 @@
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.CrashDump/Microsoft.Testing.Extensions.CrashDump.csproj b/src/Platform/Microsoft.Testing.Extensions.CrashDump/Microsoft.Testing.Extensions.CrashDump.csproj
index d69669e55b..b390f369c4 100644
--- a/src/Platform/Microsoft.Testing.Extensions.CrashDump/Microsoft.Testing.Extensions.CrashDump.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.CrashDump/Microsoft.Testing.Extensions.CrashDump.csproj
@@ -46,10 +46,6 @@ This package extends Microsoft Testing Platform to provide a crash dump function
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.HangDump/Microsoft.Testing.Extensions.HangDump.csproj b/src/Platform/Microsoft.Testing.Extensions.HangDump/Microsoft.Testing.Extensions.HangDump.csproj
index d93376e89a..7eb4a0e532 100644
--- a/src/Platform/Microsoft.Testing.Extensions.HangDump/Microsoft.Testing.Extensions.HangDump.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.HangDump/Microsoft.Testing.Extensions.HangDump.csproj
@@ -5,10 +5,6 @@
Microsoft.Testing.Extensions.Diagnostics
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.HotReload/Microsoft.Testing.Extensions.HotReload.csproj b/src/Platform/Microsoft.Testing.Extensions.HotReload/Microsoft.Testing.Extensions.HotReload.csproj
index 5c4f85a4ff..4f2ce83683 100644
--- a/src/Platform/Microsoft.Testing.Extensions.HotReload/Microsoft.Testing.Extensions.HotReload.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.HotReload/Microsoft.Testing.Extensions.HotReload.csproj
@@ -28,10 +28,6 @@ This package extends Microsoft Testing Platform to provide Hot Reload support.]]
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.MSBuild/Microsoft.Testing.Extensions.MSBuild.csproj b/src/Platform/Microsoft.Testing.Extensions.MSBuild/Microsoft.Testing.Extensions.MSBuild.csproj
index c5bf06bfbf..5048302f7b 100644
--- a/src/Platform/Microsoft.Testing.Extensions.MSBuild/Microsoft.Testing.Extensions.MSBuild.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.MSBuild/Microsoft.Testing.Extensions.MSBuild.csproj
@@ -27,10 +27,6 @@
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.OpenTelemetry/Microsoft.Testing.Extensions.OpenTelemetry.csproj b/src/Platform/Microsoft.Testing.Extensions.OpenTelemetry/Microsoft.Testing.Extensions.OpenTelemetry.csproj
index 276c796200..5901d27eb1 100644
--- a/src/Platform/Microsoft.Testing.Extensions.OpenTelemetry/Microsoft.Testing.Extensions.OpenTelemetry.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.OpenTelemetry/Microsoft.Testing.Extensions.OpenTelemetry.csproj
@@ -29,11 +29,6 @@ This package provides Open Telemetry for the platform.]]>
-
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Microsoft.Testing.Extensions.Retry.csproj b/src/Platform/Microsoft.Testing.Extensions.Retry/Microsoft.Testing.Extensions.Retry.csproj
index 7c6b529f5b..d88978beb0 100644
--- a/src/Platform/Microsoft.Testing.Extensions.Retry/Microsoft.Testing.Extensions.Retry.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Microsoft.Testing.Extensions.Retry.csproj
@@ -39,10 +39,6 @@ This package extends Microsoft Testing Platform to provide a retry policy system
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.Telemetry/Microsoft.Testing.Extensions.Telemetry.csproj b/src/Platform/Microsoft.Testing.Extensions.Telemetry/Microsoft.Testing.Extensions.Telemetry.csproj
index 3d8e7ce51c..76d4457432 100644
--- a/src/Platform/Microsoft.Testing.Extensions.Telemetry/Microsoft.Testing.Extensions.Telemetry.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.Telemetry/Microsoft.Testing.Extensions.Telemetry.csproj
@@ -48,7 +48,6 @@ This package provides telemetry for the platform.]]>
-
@@ -59,8 +58,4 @@ This package provides telemetry for the platform.]]>
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/GlobalSuppressions.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/GlobalSuppressions.cs
index c51ba7e88d..69b7059cf8 100644
--- a/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/GlobalSuppressions.cs
+++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/GlobalSuppressions.cs
@@ -4,7 +4,6 @@
// We usually do not want to suppress issues through GlobalSuppressions file but in this case we have to do it because
// we are not able to suppress the issue differently.
#pragma warning disable IDE0076
-[assembly: SuppressMessage("ApiDesign", "RS0030:Do not use banned APIs", Justification = "Source-generated file that cannot match analyzers requirements", Scope = "member", Target = "~M:Polyfill.CancelAsync(System.Threading.CancellationTokenSource)~System.Threading.Tasks.Task")]
[assembly: SuppressMessage("ApiDesign", "RS0030:Do not use banned APIs", Justification = "Source-generated file that cannot match analyzers requirements", Scope = "member", Target = "~M:System.Reflection.NullabilityInfoContext.CheckParameterMetadataType(System.Reflection.ParameterInfo,System.Reflection.NullabilityInfo)")]
[assembly: SuppressMessage("ApiDesign", "RS0030:Do not use banned APIs", Justification = "Source-generated file that cannot match analyzers requirements", Scope = "member", Target = "~M:System.Reflection.NullabilityInfoContext.Create(System.Reflection.EventInfo)~System.Reflection.NullabilityInfo")]
[assembly: SuppressMessage("ApiDesign", "RS0030:Do not use banned APIs", Justification = "Source-generated file that cannot match analyzers requirements", Scope = "member", Target = "~M:System.Reflection.NullabilityInfoContext.Create(System.Reflection.FieldInfo)~System.Reflection.NullabilityInfo")]
diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/Microsoft.Testing.Extensions.TrxReport.Abstractions.csproj b/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/Microsoft.Testing.Extensions.TrxReport.Abstractions.csproj
index 2ad2e8b49a..45d6175289 100644
--- a/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/Microsoft.Testing.Extensions.TrxReport.Abstractions.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/Microsoft.Testing.Extensions.TrxReport.Abstractions.csproj
@@ -15,12 +15,6 @@
-
-
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/PolyfillExtensions.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/PolyfillExtensions.cs
new file mode 100644
index 0000000000..c0b8aa44a4
--- /dev/null
+++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/PolyfillExtensions.cs
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#if !NET5_0_OR_GREATER
+
+internal static class TrxReportAbstractionsPolyfillExtensions
+{
+ public static global::System.Text.StringBuilder AppendJoin(this global::System.Text.StringBuilder sb, string separator, global::System.Collections.Generic.IEnumerable values)
+ {
+ bool first = true;
+ foreach (string value in values)
+ {
+ if (!first)
+ {
+ sb.Append(separator);
+ }
+
+ sb.Append(value);
+ first = false;
+ }
+
+ return sb;
+ }
+}
+
+#endif
diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/Hashing/EmbeddedAttribute.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport/Hashing/EmbeddedAttribute.cs
index 35fa4519ac..b3c7f40add 100644
--- a/src/Platform/Microsoft.Testing.Extensions.TrxReport/Hashing/EmbeddedAttribute.cs
+++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/Hashing/EmbeddedAttribute.cs
@@ -1,9 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-namespace Microsoft.CodeAnalysis;
-
-[AttributeUsage(AttributeTargets.All)]
-internal sealed partial class EmbeddedAttribute : Attribute
-{
-}
+// EmbeddedAttribute is now provided by eng/Polyfills.cs.
diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/Microsoft.Testing.Extensions.TrxReport.csproj b/src/Platform/Microsoft.Testing.Extensions.TrxReport/Microsoft.Testing.Extensions.TrxReport.csproj
index d9f92058ae..80a5bef8fe 100644
--- a/src/Platform/Microsoft.Testing.Extensions.TrxReport/Microsoft.Testing.Extensions.TrxReport.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/Microsoft.Testing.Extensions.TrxReport.csproj
@@ -63,10 +63,6 @@ This package extends Microsoft Testing Platform to provide TRX test reports.]]>
-
-
-
-
@@ -74,9 +70,6 @@ This package extends Microsoft Testing Platform to provide TRX test reports.]]>
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxCompareTool.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxCompareTool.cs
index fce5f10989..f78207c99e 100644
--- a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxCompareTool.cs
+++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxCompareTool.cs
@@ -180,7 +180,11 @@ private static void AppendResultsAndIssues(string category, string filePath,
private static async Task CollectEntriesAndErrorsAsync(string trxFile, XNamespace ns, List results, List issues)
{
using FileStream stream = File.OpenRead(trxFile);
+#if NETCOREAPP
XElement trxTestRun = await XElement.LoadAsync(stream, LoadOptions.None, CancellationToken.None).ConfigureAwait(false);
+#else
+ XElement trxTestRun = await Task.FromResult(XElement.Load(stream, LoadOptions.None)).ConfigureAwait(false);
+#endif
int testResultIndex = 0;
foreach (XElement testResult in trxTestRun.Elements(ns + "Results").Elements(ns + "UnitTestResult"))
{
diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxReportEngine.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxReportEngine.cs
index 5ea30af31c..74e1302757 100644
--- a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxReportEngine.cs
+++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxReportEngine.cs
@@ -83,7 +83,9 @@ internal sealed partial class TrxReportEngine
private readonly Dictionary> _artifactsByExtension;
private readonly ITestFramework _testFrameworkAdapter;
private readonly DateTimeOffset _testStartTime;
+#if NETCOREAPP
private readonly CancellationToken _cancellationToken;
+#endif
private readonly int _exitCode;
private readonly IFileSystem _fileSystem;
@@ -97,7 +99,11 @@ public TrxReportEngine(IFileSystem fileSystem, ITestApplicationModuleInfo testAp
_artifactsByExtension = artifactsByExtension;
_testFrameworkAdapter = testFrameworkAdapter;
_testStartTime = testStartTime;
+#if NETCOREAPP
_cancellationToken = cancellationToken;
+#else
+ _ = cancellationToken;
+#endif
_exitCode = exitCode;
_fileSystem = fileSystem;
}
@@ -174,7 +180,12 @@ public TrxReportEngine(IFileSystem fileSystem, ITestApplicationModuleInfo testAp
// Note that we need to dispose the IFileStream, not the inner stream.
// IFileStream implementations will be responsible to dispose their inner stream.
using IFileStream stream = _fileSystem.NewFileStream(finalFileName, isFileNameExplicitlyProvided ? FileMode.Create : FileMode.CreateNew);
+#if NETCOREAPP
await document.SaveAsync(stream.Stream, SaveOptions.None, _cancellationToken).ConfigureAwait(false);
+#else
+ document.Save(stream.Stream, SaveOptions.None);
+ await Task.CompletedTask.ConfigureAwait(false);
+#endif
return isFileNameExplicitlyProvidedAndFileExists
? (finalFileName, string.Format(CultureInfo.InvariantCulture, ExtensionResources.TrxFileExistsAndWillBeOverwritten, finalFileName))
: (finalFileName, null);
@@ -228,7 +239,12 @@ public async Task AddArtifactsAsync(FileInfo trxFile, Dictionary> artifacts, XElement collectorDataEntries, string runDeploymentRoot)
diff --git a/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj b/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj
index e1022bd0bd..b99991e3c4 100644
--- a/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj
@@ -17,7 +17,6 @@
-
@@ -41,8 +40,4 @@ This package provides a bridge integration for test adapters wanting to target b
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Platform.AI/Microsoft.Testing.Platform.AI.csproj b/src/Platform/Microsoft.Testing.Platform.AI/Microsoft.Testing.Platform.AI.csproj
index 402bba36b9..59516d0b3d 100644
--- a/src/Platform/Microsoft.Testing.Platform.AI/Microsoft.Testing.Platform.AI.csproj
+++ b/src/Platform/Microsoft.Testing.Platform.AI/Microsoft.Testing.Platform.AI.csproj
@@ -13,7 +13,6 @@
-
diff --git a/src/Platform/Microsoft.Testing.Platform.MSBuild/Microsoft.Testing.Platform.MSBuild.csproj b/src/Platform/Microsoft.Testing.Platform.MSBuild/Microsoft.Testing.Platform.MSBuild.csproj
index 6eb4132a3d..d8ca1f9f98 100644
--- a/src/Platform/Microsoft.Testing.Platform.MSBuild/Microsoft.Testing.Platform.MSBuild.csproj
+++ b/src/Platform/Microsoft.Testing.Platform.MSBuild/Microsoft.Testing.Platform.MSBuild.csproj
@@ -29,7 +29,6 @@
-
@@ -104,9 +103,6 @@ This package provides MSBuild integration of the platform, its extensions and co
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Platform.MSBuild/Tasks/InvokeTestingPlatformTask.cs b/src/Platform/Microsoft.Testing.Platform.MSBuild/Tasks/InvokeTestingPlatformTask.cs
index 544781520b..90deea4b64 100644
--- a/src/Platform/Microsoft.Testing.Platform.MSBuild/Tasks/InvokeTestingPlatformTask.cs
+++ b/src/Platform/Microsoft.Testing.Platform.MSBuild/Tasks/InvokeTestingPlatformTask.cs
@@ -208,7 +208,7 @@ protected override string ToolName
}
Log.LogMessage(MessageImportance.Low, $"Current process architecture '{_currentProcessArchitecture}'. Requested test architecture '{TestArchitecture.ItemSpec}'");
- PlatformArchitecture targetArchitecture = Enum.Parse(TestArchitecture.ItemSpec, ignoreCase: true);
+ var targetArchitecture = (PlatformArchitecture)Enum.Parse(typeof(PlatformArchitecture), TestArchitecture.ItemSpec, ignoreCase: true);
StringBuilder resolutionLog = new();
DotnetMuxerLocator dotnetMuxerLocator = new(log => resolutionLog.AppendLine(log));
if (dotnetMuxerLocator.TryGetDotnetPathByArchitecture(targetArchitecture, out string? dotnetPath))
@@ -242,7 +242,7 @@ protected override string ToolName
}
private bool IsCurrentProcessArchitectureCompatible() =>
- _currentProcessArchitecture == Enum.Parse(TestArchitecture.ItemSpec, ignoreCase: true);
+ _currentProcessArchitecture == (Architecture)Enum.Parse(typeof(Architecture), TestArchitecture.ItemSpec, ignoreCase: true);
private string? TryGetRunCommand()
{
diff --git a/src/Platform/Microsoft.Testing.Platform/Builder/TestApplication.cs b/src/Platform/Microsoft.Testing.Platform/Builder/TestApplication.cs
index b0b5f331e0..88391e8118 100644
--- a/src/Platform/Microsoft.Testing.Platform/Builder/TestApplication.cs
+++ b/src/Platform/Microsoft.Testing.Platform/Builder/TestApplication.cs
@@ -294,7 +294,11 @@ private static ApplicationLoggingState CreateFileLoggerIfDiagnosticIsEnabled(
if (result.TryGetOptionArgumentList(PlatformCommandLineProvider.DiagnosticVerbosityOptionKey, out string[]? verbosity))
{
+#if NET5_0_OR_GREATER
logLevel = Enum.Parse(verbosity[0], true);
+#else
+ logLevel = (LogLevel)Enum.Parse(typeof(LogLevel), verbosity[0], true);
+#endif
}
// Override the log level if the environment variable is set
diff --git a/src/Platform/Microsoft.Testing.Platform/Helpers/KeyValuePairDeconstruct.cs b/src/Platform/Microsoft.Testing.Platform/Helpers/KeyValuePairDeconstruct.cs
new file mode 100644
index 0000000000..88dd5c0c05
--- /dev/null
+++ b/src/Platform/Microsoft.Testing.Platform/Helpers/KeyValuePairDeconstruct.cs
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#if !NET5_0_OR_GREATER
+
+internal static class PolyfillKeyValuePairExtensions
+{
+ public static void Deconstruct(this System.Collections.Generic.KeyValuePair pair, out TKey key, out TValue value)
+ {
+ key = pair.Key;
+ value = pair.Value;
+ }
+}
+
+#endif
diff --git a/src/Platform/Microsoft.Testing.Platform/Helpers/Sha256Hasher.cs b/src/Platform/Microsoft.Testing.Platform/Helpers/Sha256Hasher.cs
index 019ce3a00d..bff08d361b 100644
--- a/src/Platform/Microsoft.Testing.Platform/Helpers/Sha256Hasher.cs
+++ b/src/Platform/Microsoft.Testing.Platform/Helpers/Sha256Hasher.cs
@@ -15,7 +15,16 @@ internal static class Sha256Hasher
public static string HashWithNormalizedCasing(string text)
{
byte[] bytes = Encoding.UTF8.GetBytes(text.ToUpperInvariant());
+#if NET9_0_OR_GREATER
byte[] hash = SHA256.HashData(bytes);
return Convert.ToHexStringLower(hash);
+#elif NETCOREAPP
+ byte[] hash = SHA256.HashData(bytes);
+ return Convert.ToHexString(hash).ToLowerInvariant();
+#else
+ using var sha256 = SHA256.Create();
+ byte[] hash = sha256.ComputeHash(bytes);
+ return BitConverter.ToString(hash).Replace("-", string.Empty).ToLowerInvariant();
+#endif
}
}
diff --git a/src/Platform/Microsoft.Testing.Platform/Helpers/System/SystemEnvironment.cs b/src/Platform/Microsoft.Testing.Platform/Helpers/System/SystemEnvironment.cs
index 5723b9cfa5..a1ce8c6ee7 100644
--- a/src/Platform/Microsoft.Testing.Platform/Helpers/System/SystemEnvironment.cs
+++ b/src/Platform/Microsoft.Testing.Platform/Helpers/System/SystemEnvironment.cs
@@ -12,7 +12,18 @@ internal sealed class SystemEnvironment : IEnvironment
public string NewLine => Environment.NewLine;
+#if NET5_0_OR_GREATER
public int ProcessId => Environment.ProcessId;
+#else
+ public int ProcessId
+ {
+ get
+ {
+ using var process = Process.GetCurrentProcess();
+ return process.Id;
+ }
+ }
+#endif
public string OsVersion => Environment.OSVersion.ToString();
diff --git a/src/Platform/Microsoft.Testing.Platform/Helpers/System/SystemFileSystem.cs b/src/Platform/Microsoft.Testing.Platform/Helpers/System/SystemFileSystem.cs
index d88cbf742a..9336052fcc 100644
--- a/src/Platform/Microsoft.Testing.Platform/Helpers/System/SystemFileSystem.cs
+++ b/src/Platform/Microsoft.Testing.Platform/Helpers/System/SystemFileSystem.cs
@@ -9,7 +9,19 @@ internal sealed class SystemFileSystem : IFileSystem
public string CreateDirectory(string path) => Directory.CreateDirectory(path).FullName;
+#if NET5_0_OR_GREATER
public void MoveFile(string sourceFileName, string destFileName, bool overwrite = false) => File.Move(sourceFileName, destFileName, overwrite);
+#else
+ public void MoveFile(string sourceFileName, string destFileName, bool overwrite = false)
+ {
+ if (overwrite && File.Exists(destFileName))
+ {
+ File.Delete(destFileName);
+ }
+
+ File.Move(sourceFileName, destFileName);
+ }
+#endif
public IFileStream NewFileStream(string path, FileMode mode) => new SystemFileStream(path, mode);
@@ -17,7 +29,11 @@ internal sealed class SystemFileSystem : IFileSystem
public string ReadAllText(string path) => File.ReadAllText(path);
+#if NETCOREAPP
public Task ReadAllTextAsync(string path) => File.ReadAllTextAsync(path);
+#else
+ public Task ReadAllTextAsync(string path) => Task.FromResult(File.ReadAllText(path));
+#endif
public void CopyFile(string sourceFileName, string destFileName, bool overwrite = false) => File.Copy(sourceFileName, destFileName, overwrite);
diff --git a/src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj b/src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
index 0c69386a00..c46f63bbb3 100644
--- a/src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
+++ b/src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
@@ -82,10 +82,6 @@ This package provides the core platform and the .NET implementation of the proto
-
-
-
-
diff --git a/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/SerializerUtilities.cs b/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/SerializerUtilities.cs
index 7c16ce0d93..ab042aca3f 100644
--- a/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/SerializerUtilities.cs
+++ b/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/SerializerUtilities.cs
@@ -224,7 +224,7 @@ static SerializerUtilities()
: $"{testMethodIdentifierProperty.Namespace}.{testMethodIdentifierProperty.TypeName}";
properties["location.method"] = testMethodIdentifierProperty.ParameterTypeFullNames.Length > 0
- ? $"{testMethodIdentifierProperty.MethodName}({string.Join(',', testMethodIdentifierProperty.ParameterTypeFullNames)})"
+ ? $"{testMethodIdentifierProperty.MethodName}({string.Join(",", testMethodIdentifierProperty.ParameterTypeFullNames)})"
: testMethodIdentifierProperty.MethodName;
properties["location.method-arity"] = testMethodIdentifierProperty.MethodArity;
diff --git a/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/ServerModePerCallOutputDevice.cs b/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/ServerModePerCallOutputDevice.cs
index a2783246a4..73a21a1d5e 100644
--- a/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/ServerModePerCallOutputDevice.cs
+++ b/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/ServerModePerCallOutputDevice.cs
@@ -44,7 +44,13 @@ internal async Task InitializeAsync(ServerTestHost serverTestHost)
await LogAsync(message, serverTestHost.ServiceProvider.GetTestApplicationCancellationTokenSource().CancellationToken).ConfigureAwait(false);
}
+#if NETCOREAPP
_messages.Clear();
+#else
+ while (_messages.TryTake(out _))
+ {
+ }
+#endif
}
public string Uid => nameof(ServerModePerCallOutputDevice);
diff --git a/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/TcpMessageHandler.cs b/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/TcpMessageHandler.cs
index 6267a624ab..61c4fe3c45 100644
--- a/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/TcpMessageHandler.cs
+++ b/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/TcpMessageHandler.cs
@@ -124,7 +124,12 @@ public async Task WriteRequestAsync(RpcMessage message, CancellationToken cancel
await _writer.WriteLineAsync("Content-Type: application/testingplatform").ConfigureAwait(false);
await _writer.WriteLineAsync().ConfigureAwait(false);
await _writer.WriteAsync(messageStr).ConfigureAwait(false);
+#if NET8_0_OR_GREATER
await _writer.FlushAsync(cancellationToken).ConfigureAwait(false);
+#else
+ cancellationToken.ThrowIfCancellationRequested();
+ await _writer.FlushAsync().ConfigureAwait(false);
+#endif
}
public void Dispose()
diff --git a/src/Platform/Microsoft.Testing.Platform/Services/ExecutableInfo.cs b/src/Platform/Microsoft.Testing.Platform/Services/ExecutableInfo.cs
index 17b6023e2b..80b35d1441 100644
--- a/src/Platform/Microsoft.Testing.Platform/Services/ExecutableInfo.cs
+++ b/src/Platform/Microsoft.Testing.Platform/Services/ExecutableInfo.cs
@@ -12,5 +12,5 @@ internal sealed class ExecutableInfo(string filePath, IEnumerable argume
public string Workspace { get; } = workspace;
public override string ToString()
- => $"Process: {FilePath}, Arguments: {string.Join(' ', Arguments)}, Workspace: {Workspace}";
+ => $"Process: {FilePath}, Arguments: {string.Join(" ", Arguments)}, Workspace: {Workspace}";
}
diff --git a/src/TestFramework/TestFramework.Extensions/TestFramework.Extensions.csproj b/src/TestFramework/TestFramework.Extensions/TestFramework.Extensions.csproj
index 7bd66d65a3..c7541f6f4f 100644
--- a/src/TestFramework/TestFramework.Extensions/TestFramework.Extensions.csproj
+++ b/src/TestFramework/TestFramework.Extensions/TestFramework.Extensions.csproj
@@ -56,8 +56,6 @@
-
-
@@ -81,7 +79,6 @@
-
diff --git a/src/TestFramework/TestFramework/Internal/PolyfillExtensions.cs b/src/TestFramework/TestFramework/Internal/PolyfillExtensions.cs
new file mode 100644
index 0000000000..bdf2464ea7
--- /dev/null
+++ b/src/TestFramework/TestFramework/Internal/PolyfillExtensions.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+// Polyfill extension methods for the TestFramework project which targets
+// netstandard2.0, net462, and does not have IVT from Microsoft.Testing.Platform.
+#if !NET5_0_OR_GREATER
+
+internal static class TestFrameworkPolyfillExtensions
+{
+ public static bool Contains(this string s, char c) => s.IndexOf(c) >= 0;
+
+ public static bool Contains(this string s, string value, System.StringComparison comparisonType) =>
+ s.IndexOf(value, comparisonType) >= 0;
+
+ public static bool StartsWith(this string s, char c) => s.Length > 0 && s[0] == c;
+
+ public static bool EndsWith(this string s, char c) => s.Length > 0 && s[s.Length - 1] == c;
+
+ public static void Deconstruct(this System.Collections.Generic.KeyValuePair pair, out TKey key, out TValue value)
+ {
+ key = pair.Key;
+ value = pair.Value;
+ }
+
+ public static bool TryAdd(this System.Collections.Generic.Dictionary dictionary, TKey key, TValue value)
+ where TKey : notnull
+ {
+ if (!dictionary.ContainsKey(key))
+ {
+ dictionary.Add(key, value);
+ return true;
+ }
+
+ return false;
+ }
+}
+
+#endif
diff --git a/src/TestFramework/TestFramework/Internal/TestDataSourceUtilities.cs b/src/TestFramework/TestFramework/Internal/TestDataSourceUtilities.cs
index 7ebca153fd..60a1609a0b 100644
--- a/src/TestFramework/TestFramework/Internal/TestDataSourceUtilities.cs
+++ b/src/TestFramework/TestFramework/Internal/TestDataSourceUtilities.cs
@@ -29,7 +29,7 @@ internal static class TestDataSourceUtilities
CultureInfo.CurrentCulture,
FrameworkMessages.DataDrivenResultDisplayName,
methodDisplayName,
- string.Join(',', displayData.Select(GetHumanizedArguments)));
+ string.Join(",", displayData.Select(GetHumanizedArguments)));
}
///
@@ -57,6 +57,6 @@ internal static class TestDataSourceUtilities
// We need to box the object here so that we can support value types
IEnumerable
-
-
-
-
$(EnableAotAnalyzers)
@@ -47,7 +43,6 @@
-
diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/MSTest.Acceptance.IntegrationTests.csproj b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/MSTest.Acceptance.IntegrationTests.csproj
index add7413e38..785fd9be29 100644
--- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/MSTest.Acceptance.IntegrationTests.csproj
+++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/MSTest.Acceptance.IntegrationTests.csproj
@@ -25,7 +25,6 @@
-
diff --git a/test/IntegrationTests/MSTest.IntegrationTests/MSTest.IntegrationTests.csproj b/test/IntegrationTests/MSTest.IntegrationTests/MSTest.IntegrationTests.csproj
index 5347699911..bca215eca9 100644
--- a/test/IntegrationTests/MSTest.IntegrationTests/MSTest.IntegrationTests.csproj
+++ b/test/IntegrationTests/MSTest.IntegrationTests/MSTest.IntegrationTests.csproj
@@ -27,8 +27,4 @@
-
-
-
-
diff --git a/test/IntegrationTests/MSTest.IntegrationTests/Utilities/TestCaseFilterFactory.cs b/test/IntegrationTests/MSTest.IntegrationTests/Utilities/TestCaseFilterFactory.cs
index 3bccf96779..42781b7aa2 100644
--- a/test/IntegrationTests/MSTest.IntegrationTests/Utilities/TestCaseFilterFactory.cs
+++ b/test/IntegrationTests/MSTest.IntegrationTests/Utilities/TestCaseFilterFactory.cs
@@ -7,8 +7,6 @@
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;
-using Polyfills;
-
namespace DiscoveryAndExecutionTests.Utilities;
internal static class TestCaseFilterFactory
diff --git a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests.csproj b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests.csproj
index a9b216db53..b346049c4c 100644
--- a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests.csproj
+++ b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests.csproj
@@ -18,7 +18,6 @@
-
diff --git a/test/UnitTests/MSTest.Analyzers.UnitTests/MSTest.Analyzers.UnitTests.csproj b/test/UnitTests/MSTest.Analyzers.UnitTests/MSTest.Analyzers.UnitTests.csproj
index 62237a43c6..e8eacb0909 100644
--- a/test/UnitTests/MSTest.Analyzers.UnitTests/MSTest.Analyzers.UnitTests.csproj
+++ b/test/UnitTests/MSTest.Analyzers.UnitTests/MSTest.Analyzers.UnitTests.csproj
@@ -31,8 +31,6 @@
-
-
diff --git a/test/UnitTests/MSTest.SourceGeneration.UnitTests/Generators/TestNodesGeneratorTests.cs b/test/UnitTests/MSTest.SourceGeneration.UnitTests/Generators/TestNodesGeneratorTests.cs
index 6ceb1a9ed4..36b1880807 100644
--- a/test/UnitTests/MSTest.SourceGeneration.UnitTests/Generators/TestNodesGeneratorTests.cs
+++ b/test/UnitTests/MSTest.SourceGeneration.UnitTests/Generators/TestNodesGeneratorTests.cs
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+extern alias SourceGen;
+
using AwesomeAssertions;
using Microsoft.CodeAnalysis;
@@ -8,6 +10,8 @@
using Microsoft.Testing.Framework.SourceGeneration.UnitTests.Helpers;
using Microsoft.Testing.Framework.SourceGeneration.UnitTests.TestUtilities;
+using TestNodesGenerator = SourceGen::Microsoft.Testing.Framework.SourceGeneration.TestNodesGenerator;
+
namespace Microsoft.Testing.Framework.SourceGeneration.UnitTests.Generators;
[TestClass]
diff --git a/test/UnitTests/MSTest.SourceGeneration.UnitTests/Helpers/ConstantsTests.cs b/test/UnitTests/MSTest.SourceGeneration.UnitTests/Helpers/ConstantsTests.cs
index 1944f5b664..45422e30dc 100644
--- a/test/UnitTests/MSTest.SourceGeneration.UnitTests/Helpers/ConstantsTests.cs
+++ b/test/UnitTests/MSTest.SourceGeneration.UnitTests/Helpers/ConstantsTests.cs
@@ -1,8 +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.
+extern alias SourceGen;
+
using AwesomeAssertions;
+using Constants = SourceGen::Microsoft.Testing.Framework.SourceGeneration.Constants;
+
namespace Microsoft.Testing.Framework.SourceGeneration.UnitTests;
[TestClass]
diff --git a/test/UnitTests/MSTest.SourceGeneration.UnitTests/MSTest.SourceGeneration.UnitTests.csproj b/test/UnitTests/MSTest.SourceGeneration.UnitTests/MSTest.SourceGeneration.UnitTests.csproj
index 014e756668..d762c2661e 100644
--- a/test/UnitTests/MSTest.SourceGeneration.UnitTests/MSTest.SourceGeneration.UnitTests.csproj
+++ b/test/UnitTests/MSTest.SourceGeneration.UnitTests/MSTest.SourceGeneration.UnitTests.csproj
@@ -8,6 +8,13 @@
Exe
+
+
+
+
+
+
@@ -29,6 +36,7 @@
Analyzer
true
+ SourceGen
diff --git a/test/UnitTests/MSTest.SourceGeneration.UnitTests/ObjectModels/InlineTestMethodArgumentsInfoTests.cs b/test/UnitTests/MSTest.SourceGeneration.UnitTests/ObjectModels/InlineTestMethodArgumentsInfoTests.cs
index 9c34e23745..f3a23712ea 100644
--- a/test/UnitTests/MSTest.SourceGeneration.UnitTests/ObjectModels/InlineTestMethodArgumentsInfoTests.cs
+++ b/test/UnitTests/MSTest.SourceGeneration.UnitTests/ObjectModels/InlineTestMethodArgumentsInfoTests.cs
@@ -1,7 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-using Microsoft.Testing.Framework.SourceGeneration.ObjectModels;
+extern alias SourceGen;
+
+using SourceGen::Microsoft.Testing.Framework.SourceGeneration.ObjectModels;
namespace Microsoft.Testing.Framework.SourceGeneration.UnitTests;
diff --git a/test/UnitTests/MSTest.SourceGeneration.UnitTests/TestUtilities/GeneratorTester.cs b/test/UnitTests/MSTest.SourceGeneration.UnitTests/TestUtilities/GeneratorTester.cs
index 87f1705900..0d7bdbae60 100644
--- a/test/UnitTests/MSTest.SourceGeneration.UnitTests/TestUtilities/GeneratorTester.cs
+++ b/test/UnitTests/MSTest.SourceGeneration.UnitTests/TestUtilities/GeneratorTester.cs
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+extern alias SourceGen;
+
using System.Collections.Immutable;
using AwesomeAssertions;
@@ -13,6 +15,8 @@
using Microsoft.Testing.Extensions.TrxReport.Abstractions;
using Microsoft.Testing.Platform.Extensions.Messages;
+using TestNodesGenerator = SourceGen::Microsoft.Testing.Framework.SourceGeneration.TestNodesGenerator;
+
namespace Microsoft.Testing.Framework.SourceGeneration.UnitTests.TestUtilities;
internal sealed class GeneratorTester
diff --git a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Discovery/TypeEnumeratorTests.MockedMethodInfoWithExtraAttributes.cs b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Discovery/TypeEnumeratorTests.MockedMethodInfoWithExtraAttributes.cs
index a351eada6d..9dce9a4179 100644
--- a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Discovery/TypeEnumeratorTests.MockedMethodInfoWithExtraAttributes.cs
+++ b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Discovery/TypeEnumeratorTests.MockedMethodInfoWithExtraAttributes.cs
@@ -1,10 +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.
-#if !NET6_0_OR_GREATER
-using Polyfills;
-#endif
-
namespace Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests.Discovery;
public partial class TypeEnumeratorTests
diff --git a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/MSTestAdapter.PlatformServices.UnitTests.csproj b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/MSTestAdapter.PlatformServices.UnitTests.csproj
index 5cf1911159..eacb41952d 100644
--- a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/MSTestAdapter.PlatformServices.UnitTests.csproj
+++ b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/MSTestAdapter.PlatformServices.UnitTests.csproj
@@ -32,7 +32,6 @@
-
diff --git a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/ObjectModel/UnitTestElementTests.cs b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/ObjectModel/UnitTestElementTests.cs
index c71f23c72b..b0fbc6612f 100644
--- a/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/ObjectModel/UnitTestElementTests.cs
+++ b/test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/ObjectModel/UnitTestElementTests.cs
@@ -158,7 +158,7 @@ public void ToTestCaseShouldSetDeploymentItemPropertyIfPresent()
public void ToTestCase_WhenStrategyIsData_DoesNotUseDefaultTestCaseId()
{
#pragma warning disable CA2263 // Prefer generic overload when type is known
- foreach (DynamicDataType dataType in Enum.GetValues())
+ foreach (DynamicDataType dataType in Enum.GetValues(typeof(DynamicDataType)))
{
var testCase = new UnitTestElement(new("MyMethod", "MyProduct.MyNamespace.MyClass", "MyAssembly", null)
{
diff --git a/test/UnitTests/MSTestAdapter.UnitTests/MSTestAdapter.UnitTests.csproj b/test/UnitTests/MSTestAdapter.UnitTests/MSTestAdapter.UnitTests.csproj
index 6ca3cab48e..430e00aca3 100644
--- a/test/UnitTests/MSTestAdapter.UnitTests/MSTestAdapter.UnitTests.csproj
+++ b/test/UnitTests/MSTestAdapter.UnitTests/MSTestAdapter.UnitTests.csproj
@@ -31,7 +31,6 @@
-
diff --git a/test/UnitTests/Microsoft.Testing.Extensions.UnitTests/Microsoft.Testing.Extensions.UnitTests.csproj b/test/UnitTests/Microsoft.Testing.Extensions.UnitTests/Microsoft.Testing.Extensions.UnitTests.csproj
index 62289d70b7..c9d3c403b3 100644
--- a/test/UnitTests/Microsoft.Testing.Extensions.UnitTests/Microsoft.Testing.Extensions.UnitTests.csproj
+++ b/test/UnitTests/Microsoft.Testing.Extensions.UnitTests/Microsoft.Testing.Extensions.UnitTests.csproj
@@ -34,7 +34,6 @@
-
diff --git a/test/UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests.csproj b/test/UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests.csproj
index 65ac530917..d91be2a25e 100644
--- a/test/UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests.csproj
+++ b/test/UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests.csproj
@@ -17,7 +17,6 @@
-
diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/Microsoft.Testing.Platform.UnitTests.csproj b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/Microsoft.Testing.Platform.UnitTests.csproj
index 954782fee0..bbe88bba2a 100644
--- a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/Microsoft.Testing.Platform.UnitTests.csproj
+++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/Microsoft.Testing.Platform.UnitTests.csproj
@@ -34,16 +34,12 @@
-
-
-
-
diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreEqualTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreEqualTests.cs
index 1ba1daaad9..f7901cfdce 100644
--- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreEqualTests.cs
+++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreEqualTests.cs
@@ -1649,7 +1649,7 @@ public void CreateStringPreviews_DiffNeverPointsAtEllipsis_Generated()
{
string p = FormatStringPreview(StringPreviewHelper.CreateStringPreviews(DigitString(e, d), DigitString(a, d), diffIndex: d, 11));
- string[] lines = p.Split("\n");
+ string[] lines = p.Split('\n');
int diffIndicator = lines[2].IndexOf('^');
bool line0PointsOnEllipsis = lines[0].Length > diffIndicator && lines[0][diffIndicator] == '.';
bool line1PointsOnEllipsis = lines[1].Length > diffIndicator && lines[1][diffIndicator] == '.';
diff --git a/test/UnitTests/TestFramework.UnitTests/TestFramework.UnitTests.csproj b/test/UnitTests/TestFramework.UnitTests/TestFramework.UnitTests.csproj
index 6b9b4137dc..e5266ccc69 100644
--- a/test/UnitTests/TestFramework.UnitTests/TestFramework.UnitTests.csproj
+++ b/test/UnitTests/TestFramework.UnitTests/TestFramework.UnitTests.csproj
@@ -24,7 +24,6 @@
-
diff --git a/test/Utilities/Automation.CLI/Automation.CLI.csproj b/test/Utilities/Automation.CLI/Automation.CLI.csproj
index cbb4fe349f..85328da591 100644
--- a/test/Utilities/Automation.CLI/Automation.CLI.csproj
+++ b/test/Utilities/Automation.CLI/Automation.CLI.csproj
@@ -7,7 +7,6 @@
-
diff --git a/test/Utilities/Microsoft.Testing.TestInfrastructure/Microsoft.Testing.TestInfrastructure.csproj b/test/Utilities/Microsoft.Testing.TestInfrastructure/Microsoft.Testing.TestInfrastructure.csproj
index 73bb77b1b6..497f5dd6ff 100644
--- a/test/Utilities/Microsoft.Testing.TestInfrastructure/Microsoft.Testing.TestInfrastructure.csproj
+++ b/test/Utilities/Microsoft.Testing.TestInfrastructure/Microsoft.Testing.TestInfrastructure.csproj
@@ -9,7 +9,6 @@
-
@@ -17,8 +16,4 @@
-
-
-
-
diff --git a/test/Utilities/TestFramework.ForTestingMSTest/TestFramework.ForTestingMSTest.csproj b/test/Utilities/TestFramework.ForTestingMSTest/TestFramework.ForTestingMSTest.csproj
index 23bdfc6d46..49ac091178 100644
--- a/test/Utilities/TestFramework.ForTestingMSTest/TestFramework.ForTestingMSTest.csproj
+++ b/test/Utilities/TestFramework.ForTestingMSTest/TestFramework.ForTestingMSTest.csproj
@@ -15,8 +15,4 @@
-
-
-
-