diff --git a/Directory.Build.props b/Directory.Build.props
index fe3901dfe7..612bacd835 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -29,7 +29,7 @@
net9.0-windows10.0.17763.0
net8.0-windows10.0.18362.0
- net8.0;net9.0
+ net8.0;net10.0
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 6a717699fb..68fcd69b60 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,29 +1,29 @@
-
+
https://github.com/dotnet/arcade
- 3ed6c23fee67b840de0fb5473ea6a95fc667b0a9
+ 8a7b2d3d39078db20f33067c7929b88fdff4ee63
-
+
https://github.com/dotnet/arcade
- 3ed6c23fee67b840de0fb5473ea6a95fc667b0a9
+ 8a7b2d3d39078db20f33067c7929b88fdff4ee63
-
+
https://github.com/dotnet/arcade
- 3ed6c23fee67b840de0fb5473ea6a95fc667b0a9
+ 8a7b2d3d39078db20f33067c7929b88fdff4ee63
https://dev.azure.com/devdiv/DevDiv/_git/vs-code-coverage
6b29c14c934bae1e26c21961b7e5ad1a25c4d3c5
-
+
https://github.com/microsoft/testfx
- 0da10c24091f1ad35610ac05dd5aa7bd3ea79dd5
+ e6af9df44f1c17bcae2798b15388641609add3a3
-
+
https://github.com/microsoft/testfx
- 0da10c24091f1ad35610ac05dd5aa7bd3ea79dd5
+ e6af9df44f1c17bcae2798b15388641609add3a3
diff --git a/eng/Versions.props b/eng/Versions.props
index 61ec584c48..0aea2be2c8 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -7,10 +7,10 @@
preview
- 11.0.0-beta.26229.1
+ 11.0.0-beta.26230.2
18.8.0-preview.26229.1
- 4.3.0-preview.26229.1
- 2.3.0-preview.26229.1
+ 4.3.0-preview.26230.4
+ 2.3.0-preview.26230.4
diff --git a/eng/common/AGENTS.md b/eng/common/AGENTS.md
new file mode 100644
index 0000000000..a5ed8f7292
--- /dev/null
+++ b/eng/common/AGENTS.md
@@ -0,0 +1,5 @@
+# `eng/common`
+
+Files under `eng/common` come from [Arcade](https://github.com/dotnet/arcade).
+Edits in `eng/common` will be overwritten by automation unless the changes are made directly in the Arcade repository.
+For more information, see the [Arcade documentation](https://github.com/dotnet/arcade/tree/main/Documentation).
diff --git a/global.json b/global.json
index bb3dafdc76..4ca072a911 100644
--- a/global.json
+++ b/global.json
@@ -37,7 +37,7 @@
"runner": "Microsoft.Testing.Platform"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "11.0.0-beta.26229.1",
+ "Microsoft.DotNet.Arcade.Sdk": "11.0.0-beta.26230.2",
"MSBuild.Sdk.Extras": "3.0.44"
}
}
diff --git a/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestDiscoverer.cs b/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestDiscoverer.cs
index 5b46c15750..9f410c1740 100644
--- a/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestDiscoverer.cs
+++ b/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestDiscoverer.cs
@@ -43,6 +43,11 @@ public void DiscoverTests(IEnumerable sources, IDiscoveryContext discove
internal void DiscoverTests(IEnumerable sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink, IConfiguration? configuration, bool isMTP)
{
+#if NET6_0_OR_GREATER
+ ArgumentNullException.ThrowIfNull(sources);
+ ArgumentNullException.ThrowIfNull(logger);
+ ArgumentNullException.ThrowIfNull(discoverySink);
+#else
if (sources is null)
{
throw new ArgumentNullException(nameof(sources));
@@ -57,6 +62,7 @@ internal void DiscoverTests(IEnumerable sources, IDiscoveryContext disco
{
throw new ArgumentNullException(nameof(discoverySink));
}
+#endif
if (MSTestDiscovererHelpers.InitializeDiscovery(sources, discoveryContext, logger, configuration, _testSourceHandler))
{
diff --git a/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestExecutor.cs b/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestExecutor.cs
index 098ac21a30..995df40e0b 100644
--- a/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestExecutor.cs
+++ b/src/Adapter/MSTest.TestAdapter/VSTestAdapter/MSTestExecutor.cs
@@ -102,6 +102,10 @@ internal async Task RunTestsAsync(IEnumerable? tests, IRunContext? run
PlatformServiceProvider.Instance.AdapterTraceLogger.Info("MSTestExecutor.RunTests: Running tests from testcases.");
}
+#if NET6_0_OR_GREATER
+ ArgumentNullException.ThrowIfNull(frameworkHandle);
+ ArgumentNullException.ThrowIfNull(tests);
+#else
if (frameworkHandle is null)
{
throw new ArgumentNullException(nameof(frameworkHandle));
@@ -112,6 +116,7 @@ internal async Task RunTestsAsync(IEnumerable? tests, IRunContext? run
{
throw new ArgumentNullException(nameof(tests));
}
+#endif
Ensure.NotEmpty(tests);
@@ -130,6 +135,10 @@ internal async Task RunTestsAsync(IEnumerable? sources, IRunContext? run
PlatformServiceProvider.Instance.AdapterTraceLogger.Info("MSTestExecutor.RunTests: Running tests from sources.");
}
+#if NET6_0_OR_GREATER
+ ArgumentNullException.ThrowIfNull(frameworkHandle);
+ ArgumentNullException.ThrowIfNull(sources);
+#else
if (frameworkHandle is null)
{
throw new ArgumentNullException(nameof(frameworkHandle));
@@ -140,6 +149,7 @@ internal async Task RunTestsAsync(IEnumerable? sources, IRunContext? run
{
throw new ArgumentNullException(nameof(sources));
}
+#endif
Ensure.NotEmpty(sources);
diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Execution/ClassCleanupManager.cs b/src/Adapter/MSTestAdapter.PlatformServices/Execution/ClassCleanupManager.cs
index b64888c573..648d6e8bc9 100644
--- a/src/Adapter/MSTestAdapter.PlatformServices/Execution/ClassCleanupManager.cs
+++ b/src/Adapter/MSTestAdapter.PlatformServices/Execution/ClassCleanupManager.cs
@@ -5,28 +5,57 @@
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+#if NET8_0_OR_GREATER
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+#endif
namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Execution;
internal sealed class ClassCleanupManager
{
- private readonly ConcurrentDictionary _remainingTestCountsByClass;
+#if NET9_0_OR_GREATER
+ private readonly Lock _lock = new();
+#else
+ private readonly object _lock = new();
+#endif
+ private readonly Dictionary _remainingTestCountsByClass;
public ClassCleanupManager(IEnumerable testsToRun)
{
_remainingTestCountsByClass =
- new(testsToRun.GroupBy(t => t.TestMethod.FullClassName)
+ testsToRun.GroupBy(t => t.TestMethod.FullClassName)
.ToDictionary(
g => g.Key,
- g => g.Count()));
+ g => g.Count());
}
- public bool ShouldRunEndOfAssemblyCleanup => _remainingTestCountsByClass.IsEmpty;
+ public bool ShouldRunEndOfAssemblyCleanup
+ {
+ get
+ {
+ lock (_lock)
+ {
+ return _remainingTestCountsByClass.Count == 0;
+ }
+ }
+ }
public void MarkTestComplete(TestMethod testMethod, out bool isLastTestInClass)
{
- lock (_remainingTestCountsByClass)
+ lock (_lock)
{
+#if NET8_0_OR_GREATER
+ ref int remainingCount = ref CollectionsMarshal.GetValueRefOrNullRef(
+ _remainingTestCountsByClass, testMethod.FullClassName);
+ if (Unsafe.IsNullRef(ref remainingCount))
+ {
+ throw ApplicationStateGuard.Unreachable();
+ }
+
+ remainingCount--;
+ isLastTestInClass = remainingCount == 0;
+#else
if (!_remainingTestCountsByClass.TryGetValue(testMethod.FullClassName, out int remainingCount))
{
throw ApplicationStateGuard.Unreachable();
@@ -35,20 +64,23 @@ public void MarkTestComplete(TestMethod testMethod, out bool isLastTestInClass)
remainingCount--;
_remainingTestCountsByClass[testMethod.FullClassName] = remainingCount;
isLastTestInClass = remainingCount == 0;
+#endif
}
}
public void MarkClassComplete(string fullClassName)
{
- lock (_remainingTestCountsByClass)
+ lock (_lock)
{
- if (!_remainingTestCountsByClass.TryRemove(fullClassName, out int remainingTests) ||
+ if (!_remainingTestCountsByClass.TryGetValue(fullClassName, out int remainingTests) ||
remainingTests != 0)
{
- // We failed to remove the class, or we are incorrectly marking the class as complete while there are remaining tests.
+ // We failed to find the class, or we are incorrectly marking the class as complete while there are remaining tests.
// This should never happen.
throw ApplicationStateGuard.Unreachable();
}
+
+ _remainingTestCountsByClass.Remove(fullClassName);
}
}
diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/RandomId.cs b/src/Platform/Microsoft.Testing.Extensions.Retry/RandomId.cs
index 1f1181702a..516272391e 100644
--- a/src/Platform/Microsoft.Testing.Extensions.Retry/RandomId.cs
+++ b/src/Platform/Microsoft.Testing.Extensions.Retry/RandomId.cs
@@ -12,6 +12,11 @@ namespace Microsoft.Testing.Extensions;
internal static class RandomId
{
private const string Pool = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+#if NET9_0_OR_GREATER
+ private static readonly Lock s_lock = new();
+#else
+ private static readonly object s_lock = new();
+#endif
private static readonly RandomNumberGenerator Rng = RandomNumberGenerator.Create();
///
@@ -23,7 +28,7 @@ private static string Next(int length)
{
int poolLength = Pool.Length;
char[] id = new char[length];
- lock (Pool)
+ lock (s_lock)
{
for (int idIndex = 0; idIndex < length; idIndex++)
{
diff --git a/src/Platform/Microsoft.Testing.Platform/Logging/TypeNameHelper.cs b/src/Platform/Microsoft.Testing.Platform/Logging/TypeNameHelper.cs
index addac6ed99..a3caa41593 100644
--- a/src/Platform/Microsoft.Testing.Platform/Logging/TypeNameHelper.cs
+++ b/src/Platform/Microsoft.Testing.Platform/Logging/TypeNameHelper.cs
@@ -1,6 +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.
+#if NET8_0_OR_GREATER
+using System.Collections.Frozen;
+#endif
+
namespace Microsoft.Testing.Platform.Logging;
///
@@ -11,6 +15,27 @@ internal static class TypeNameHelper
{
private const char DefaultNestedTypeDelimiter = '+';
+#if NET8_0_OR_GREATER
+ private static readonly FrozenDictionary BuiltInTypeNames = new Dictionary
+ {
+ { typeof(void), "void" },
+ { typeof(bool), "bool" },
+ { typeof(byte), "byte" },
+ { typeof(char), "char" },
+ { typeof(decimal), "decimal" },
+ { typeof(double), "double" },
+ { typeof(float), "float" },
+ { typeof(int), "int" },
+ { typeof(long), "long" },
+ { typeof(object), "object" },
+ { typeof(sbyte), "sbyte" },
+ { typeof(short), "short" },
+ { typeof(string), "string" },
+ { typeof(uint), "uint" },
+ { typeof(ulong), "ulong" },
+ { typeof(ushort), "ushort" },
+ }.ToFrozenDictionary();
+#else
private static readonly Dictionary BuiltInTypeNames = new()
{
{ typeof(void), "void" },
@@ -30,6 +55,7 @@ internal static class TypeNameHelper
{ typeof(ulong), "ulong" },
{ typeof(ushort), "ushort" },
};
+#endif
///
/// Pretty print a type name.
diff --git a/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/SerializerUtilities.cs b/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/SerializerUtilities.cs
index 0d1a572f86..daa9ae7a89 100644
--- a/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/SerializerUtilities.cs
+++ b/src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/SerializerUtilities.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// Note: System.Text.Json is only available in .NET 6.0 and above.
@@ -6,6 +6,9 @@
#if !NETCOREAPP
using Jsonite;
#endif
+#if NET8_0_OR_GREATER
+using System.Collections.Frozen;
+#endif
using Microsoft.Testing.Platform.Extensions.Messages;
using Microsoft.Testing.Platform.Helpers;
@@ -13,8 +16,13 @@ namespace Microsoft.Testing.Platform.ServerMode;
internal static class SerializerUtilities
{
+#if NET8_0_OR_GREATER
+ private static readonly FrozenDictionary Serializers;
+ private static readonly FrozenDictionary Deserializers;
+#else
private static readonly Dictionary Serializers;
private static readonly Dictionary Deserializers;
+#endif
///
/// Initializes static members of the class.
@@ -23,11 +31,11 @@ internal static class SerializerUtilities
///
static SerializerUtilities()
{
- Serializers = [];
- Deserializers = [];
+ var serializers = new Dictionary();
+ var deserializers = new Dictionary();
- Serializers[typeof(object)] = new ObjectSerializer