Skip to content

Commit 08900d6

Browse files
Add repro test for batching hang issue
Co-authored-by: electricessence <5899455+electricessence@users.noreply.github.com>
1 parent 7d5b8a9 commit 08900d6

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System.Text.Json;
2+
3+
namespace Open.ChannelExtensions.Tests;
4+
5+
public static class HangReproTest
6+
{
7+
/// <summary>
8+
/// Reproduction test for the hanging issue described in GitHub.
9+
/// This test should fail if the bug exists (by timing out).
10+
/// </summary>
11+
[Fact]
12+
public static async Task MultipleBatchReadersDoNotHang()
13+
{
14+
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); // 30 second timeout
15+
var token = cts.Token;
16+
17+
var counts = new int[5]; // Using 5 tasks instead of 10 for faster testing
18+
var tasks = Enumerable.Range(0, 5)
19+
.Select(x => Task.Run(async () =>
20+
{
21+
for (int i = 0; i < 50; i++) // Run 50 iterations instead of infinite
22+
{
23+
if (token.IsCancellationRequested)
24+
break;
25+
26+
await GetSource()
27+
.ToChannel(singleReader: true, cancellationToken: token)
28+
.Batch(Random.Shared.Next(15, 30), singleReader: true)
29+
.ReadAllAsync(async batch =>
30+
{
31+
await Task.Delay(Random.Shared.Next(2, 15), token);
32+
}, token);
33+
34+
counts[x] += 1;
35+
}
36+
}, token)).ToArray();
37+
38+
// Wait for all tasks to complete or timeout
39+
await Task.WhenAll(tasks);
40+
41+
// Verify all tasks completed at least some iterations
42+
Assert.All(counts, count => Assert.True(count >= 40, $"Count was {count}, expected at least 40"));
43+
}
44+
45+
private static async IAsyncEnumerable<int> GetSource([System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
46+
{
47+
foreach (var value in Enumerable.Range(0, Random.Shared.Next(80, 120)))
48+
{
49+
if (cancellationToken.IsCancellationRequested)
50+
yield break;
51+
52+
yield return value;
53+
54+
if (value % Random.Shared.Next(15, 25) == 0)
55+
await Task.Delay(Random.Shared.Next(2, 15), cancellationToken);
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)