From 903e49a47a7a3226947c15e3974b53bdc8b0806e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 20:22:39 +0000 Subject: [PATCH 1/3] Initial plan From ff0b288038c2926fe2b3621cb9e993745f6f1f5d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 20:34:11 +0000 Subject: [PATCH 2/3] Fix Dataflow test timeouts: add 30s timeout to SpinWait.SpinUntil calls Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> --- .../tests/Dataflow/ConcurrentTests.cs | 12 ++++++------ .../tests/Dataflow/TransformBlockTests.cs | 2 +- .../TransformManyBlockTests.IAsyncEnumerable.cs | 2 +- .../tests/Dataflow/TransformManyBlockTests.cs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/ConcurrentTests.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/ConcurrentTests.cs index 1f8ed5777074f3..e61b2144438af3 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/ConcurrentTests.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/ConcurrentTests.cs @@ -163,7 +163,7 @@ private static BufferBlock ConstructBufferNewWithNMessages(int messagesCoun { var block = new BufferBlock(); block.PostRange(0, messagesCount); - SpinWait.SpinUntil(() => block.Count == messagesCount); // spin until messages available + Assert.True(SpinWait.SpinUntil(() => block.Count == messagesCount, 30_000)); // spin until messages available return block; } @@ -171,7 +171,7 @@ private static TransformBlock ConstructTransformWithNMessages(int m { var block = new TransformBlock(i => i.ToString()); block.PostRange(0, messagesCount); - SpinWait.SpinUntil(() => block.OutputCount == messagesCount); + Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, 30_000)); return block; } @@ -179,7 +179,7 @@ private static TransformManyBlock ConstructTransformManyWithNMessages( { var block = new TransformManyBlock(i => new int[] { i }); block.PostRange(0, messagesCount); - SpinWait.SpinUntil(() => block.OutputCount == messagesCount); // spin until messages available + Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, 30_000)); // spin until messages available return block; } @@ -187,7 +187,7 @@ private static BatchBlock ConstructBatchNewWithNMessages(int messagesCount) { var block = new BatchBlock(1); block.PostRange(0, messagesCount); - SpinWait.SpinUntil(() => block.OutputCount == messagesCount); // spin until messages available + Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, 30_000)); // spin until messages available return block; } @@ -199,7 +199,7 @@ private static BatchedJoinBlock ConstructBatchedJoin2NewWithNMessages( block.Target1.Post(i); block.Target2.Post(i); } - SpinWait.SpinUntil(() => block.OutputCount == messagesCount); // spin until messages available + Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, 30_000)); // spin until messages available return block; } @@ -223,7 +223,7 @@ private static JoinBlock ConstructJoinNewWithNMessages(int messagesCou var block = new JoinBlock(); block.Target1.PostRange(0, messagesCount); block.Target2.PostRange(0, messagesCount); - SpinWait.SpinUntil(() => block.OutputCount == messagesCount); // spin until messages available + Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, 30_000)); // spin until messages available return block; } diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformBlockTests.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformBlockTests.cs index 069abcee3c745c..dbbcb740018a34 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformBlockTests.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformBlockTests.cs @@ -324,7 +324,7 @@ public async Task TestCount() Assert.Equal(expected: 0, actual: tb.OutputCount); tb.PostRange(1, 11); - await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10)); + Assert.True(await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10, 30_000))); for (int i = 10; i > 0; i--) { int item; diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.IAsyncEnumerable.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.IAsyncEnumerable.cs index 73205b6057341f..71913fd65f7680 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.IAsyncEnumerable.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.IAsyncEnumerable.cs @@ -339,7 +339,7 @@ public async Task TestCountAsyncEnumerable() Assert.Equal(expected: 0, actual: tb.OutputCount); tb.PostRange(1, 11); - await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10)); + Assert.True(await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10, 30_000))); for (int i = 10; i > 0; i--) { Assert.True(tb.TryReceive(out int item)); diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.cs index 53e4bf816a4d40..63ee3a419c3289 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.cs @@ -352,7 +352,7 @@ public async Task TestCount() Assert.Equal(expected: 0, actual: tb.OutputCount); tb.PostRange(1, 11); - await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10)); + Assert.True(await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10, 30_000))); for (int i = 10; i > 0; i--) { int item; From 81299538a098565da0c340d454654e2bb2c14d68 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 20:46:39 +0000 Subject: [PATCH 3/3] Extract SpinTimeoutMs constant to DataflowTestHelpers Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> --- .../tests/Dataflow/ConcurrentTests.cs | 12 ++++++------ .../tests/Dataflow/DataflowTestHelper.cs | 3 +++ .../tests/Dataflow/TransformBlockTests.cs | 2 +- .../TransformManyBlockTests.IAsyncEnumerable.cs | 2 +- .../tests/Dataflow/TransformManyBlockTests.cs | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/ConcurrentTests.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/ConcurrentTests.cs index e61b2144438af3..88c9f4b30b83b4 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/ConcurrentTests.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/ConcurrentTests.cs @@ -163,7 +163,7 @@ private static BufferBlock ConstructBufferNewWithNMessages(int messagesCoun { var block = new BufferBlock(); block.PostRange(0, messagesCount); - Assert.True(SpinWait.SpinUntil(() => block.Count == messagesCount, 30_000)); // spin until messages available + Assert.True(SpinWait.SpinUntil(() => block.Count == messagesCount, DataflowTestHelpers.SpinTimeoutMs)); // spin until messages available return block; } @@ -171,7 +171,7 @@ private static TransformBlock ConstructTransformWithNMessages(int m { var block = new TransformBlock(i => i.ToString()); block.PostRange(0, messagesCount); - Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, 30_000)); + Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, DataflowTestHelpers.SpinTimeoutMs)); return block; } @@ -179,7 +179,7 @@ private static TransformManyBlock ConstructTransformManyWithNMessages( { var block = new TransformManyBlock(i => new int[] { i }); block.PostRange(0, messagesCount); - Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, 30_000)); // spin until messages available + Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, DataflowTestHelpers.SpinTimeoutMs)); // spin until messages available return block; } @@ -187,7 +187,7 @@ private static BatchBlock ConstructBatchNewWithNMessages(int messagesCount) { var block = new BatchBlock(1); block.PostRange(0, messagesCount); - Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, 30_000)); // spin until messages available + Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, DataflowTestHelpers.SpinTimeoutMs)); // spin until messages available return block; } @@ -199,7 +199,7 @@ private static BatchedJoinBlock ConstructBatchedJoin2NewWithNMessages( block.Target1.Post(i); block.Target2.Post(i); } - Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, 30_000)); // spin until messages available + Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, DataflowTestHelpers.SpinTimeoutMs)); // spin until messages available return block; } @@ -223,7 +223,7 @@ private static JoinBlock ConstructJoinNewWithNMessages(int messagesCou var block = new JoinBlock(); block.Target1.PostRange(0, messagesCount); block.Target2.PostRange(0, messagesCount); - Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, 30_000)); // spin until messages available + Assert.True(SpinWait.SpinUntil(() => block.OutputCount == messagesCount, DataflowTestHelpers.SpinTimeoutMs)); // spin until messages available return block; } diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowTestHelper.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowTestHelper.cs index 3dbabb20246d74..8679d3908bb071 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowTestHelper.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowTestHelper.cs @@ -12,6 +12,9 @@ internal static partial class DataflowTestHelpers internal static bool[] BooleanValues = { true, false }; internal static Func> ToEnumerable = item => Enumerable.Repeat(item, 1); + /// Timeout in milliseconds for spin-wait operations in tests, to avoid indefinite hangs under stress. + internal const int SpinTimeoutMs = 30_000; + internal static ITargetBlock PostRange(this ITargetBlock target, int lowerBoundInclusive, int upperBoundExclusive) { return PostRange(target, lowerBoundInclusive, upperBoundExclusive, i => i); diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformBlockTests.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformBlockTests.cs index dbbcb740018a34..6934cc51bb52cf 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformBlockTests.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformBlockTests.cs @@ -324,7 +324,7 @@ public async Task TestCount() Assert.Equal(expected: 0, actual: tb.OutputCount); tb.PostRange(1, 11); - Assert.True(await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10, 30_000))); + Assert.True(await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10, DataflowTestHelpers.SpinTimeoutMs))); for (int i = 10; i > 0; i--) { int item; diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.IAsyncEnumerable.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.IAsyncEnumerable.cs index 71913fd65f7680..f92413c804bb7c 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.IAsyncEnumerable.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.IAsyncEnumerable.cs @@ -339,7 +339,7 @@ public async Task TestCountAsyncEnumerable() Assert.Equal(expected: 0, actual: tb.OutputCount); tb.PostRange(1, 11); - Assert.True(await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10, 30_000))); + Assert.True(await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10, DataflowTestHelpers.SpinTimeoutMs))); for (int i = 10; i > 0; i--) { Assert.True(tb.TryReceive(out int item)); diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.cs index 63ee3a419c3289..6f32a0d246fbeb 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/TransformManyBlockTests.cs @@ -352,7 +352,7 @@ public async Task TestCount() Assert.Equal(expected: 0, actual: tb.OutputCount); tb.PostRange(1, 11); - Assert.True(await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10, 30_000))); + Assert.True(await Task.Run(() => SpinWait.SpinUntil(() => tb.OutputCount == 10, DataflowTestHelpers.SpinTimeoutMs))); for (int i = 10; i > 0; i--) { int item;