using System.IO.Pipelines;
using AyCode.Services.SignalRs;
using Microsoft.AspNetCore.SignalR.Protocol;
namespace AyCode.Services.Server.Tests.SignalRs;
///
/// Thread-pool starvation regression tests for the AsyncSegment paths
/// (ACCORE-SBP-I-T3W9: blocking waits on .NET thread-pool threads deadlock the pool under
/// concurrent load + real network latency — production-only, "stuck loading → 60 s timeout").
///
/// Deser (receive) side — fixed. The streaming deser blocks in
/// ManualResetEventSlim.Wait() between network-delivered chunks. It now runs off the .NET
/// thread pool on a never-queue + reuse dedicated executor () so
/// the blocking wait never consumes a pool thread (which the producer's receive-continuations need
/// → circular dependency). These tests assert that executor contract directly and should all pass.
///
/// Ser (send) side — TBD. The per-chunk SyncFlush in WriteMessageChunked
/// blocks a dispatch (pool) thread under client backpressure. The send-side test below asserts the
/// DESIRED non-blocking behaviour and is [Ignore]d until that fix lands.
///
[TestClass]
public class AcBinaryProtocolThreadPoolTests
{
// ---------------------------------------------------------------------------------------------
// Deser (receive) side — AcBinaryDeserExecutor contract. Expected: all pass.
// ---------------------------------------------------------------------------------------------
[TestMethod]
public void DeserExecutor_RunsOffThreadPool()
{
var onPool = (bool)AcBinaryDeserExecutor.Run(() => (object?)Thread.CurrentThread.IsThreadPoolThread).GetAwaiter().GetResult()!;
Assert.IsFalse(onPool,
"Streaming deser must run OFF the .NET thread pool (dedicated thread) — the blocking " +
"MRES.Wait() would otherwise pin a pool thread the producer's receive-continuation needs " +
"→ circular-dependency starvation (ACCORE-SBP-I-T3W9).");
}
[TestMethod]
public void DeserExecutor_NeverQueues_AllConcurrentWorkStartsImmediately()
{
const int n = 32;
using var allStarted = new CountdownEvent(n);
using var release = new ManualResetEventSlim(false);
var tasks = new Task