From 61ee139ffce05ddaaafda9ee05c440b80fa5f4ca Mon Sep 17 00:00:00 2001 From: vsadov <8218165+VSadov@users.noreply.github.com> Date: Tue, 14 Oct 2025 08:57:06 -0700 Subject: [PATCH 1/2] make a test compatible with runtime async. --- .../AsyncTaskMethodBuilderTests.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs index 102262dea7bd5f..932f32451b507b 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs @@ -670,8 +670,12 @@ public void AsyncTaskMethodBuilder_Completed_RemovedFromTracking() t.Wait(); } - int activeCount = ((dynamic)typeof(Task).GetField("s_currentActiveTasks", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null)).Count; - Assert.InRange(activeCount, 0, 10); // some other tasks may be created by the runtime, so this is just using a reasonably small upper bound + object activeTasks = typeof(Task).GetField("s_currentActiveTasks", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); + if (activeTasks is not null) + { + int activeCount = ((dynamic)activeTasks).Count; + Assert.InRange(activeCount, 0, 10); // some other tasks may be created by the runtime, so this is just using a reasonably small upper bound + } }).Dispose(); } From 7dac728e29713028817fb4c0522a690d9300f1ca Mon Sep 17 00:00:00 2001 From: vsadov <8218165+VSadov@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:19:29 -0700 Subject: [PATCH 2/2] use UnsafeAccessor --- .../AsyncTaskMethodBuilderTests.cs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs index 932f32451b507b..d803b0e6009a84 100644 --- a/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs +++ b/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs @@ -651,14 +651,22 @@ public static void DroppedIncompleteStateMachine_RaisesIncompleteAsyncMethodEven }).Dispose(); } + // NOTE: This depends on private implementation details generally only used by the debugger. + // If those ever change, this test will need to be updated as well. + [UnsafeAccessor(UnsafeAccessorKind.StaticField, Name = "s_asyncDebuggingEnabled")] + private extern static ref bool AsyncDebuggingEnabled(Task t); + + // NOTE: This depends on private implementation details generally only used by the debugger. + // If those ever change, this test will need to be updated as well. + [UnsafeAccessor(UnsafeAccessorKind.StaticField, Name = "s_currentActiveTasks")] + private extern static ref Dictionary? CurrentActiveTasks(Task t); + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void AsyncTaskMethodBuilder_Completed_RemovedFromTracking() { RemoteExecutor.Invoke(() => { - // NOTE: This depends on private implementation details generally only used by the debugger. - // If those ever change, this test will need to be updated as well. - typeof(Task).GetField("s_asyncDebuggingEnabled", BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, true); + AsyncDebuggingEnabled(null) = true; for (int i = 0; i < 1000; i++) { @@ -670,12 +678,10 @@ public void AsyncTaskMethodBuilder_Completed_RemovedFromTracking() t.Wait(); } - object activeTasks = typeof(Task).GetField("s_currentActiveTasks", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); - if (activeTasks is not null) - { - int activeCount = ((dynamic)activeTasks).Count; - Assert.InRange(activeCount, 0, 10); // some other tasks may be created by the runtime, so this is just using a reasonably small upper bound - } + Dictionary? activeTasks = CurrentActiveTasks(null); + int activeCount = activeTasks?.Count ?? 0; + Assert.InRange(activeCount, 0, 10); // some other tasks may be created by the runtime, so this is just using a reasonably small upper bound + }).Dispose(); }