using System.Net; using DeepDrftModels.Enums; using DeepDrftPublic.Client.Clients; namespace DeepDrftTests; /// /// Pins the Phase 21.4 transport fix: every audio media fetch must carry the browser response-streaming /// option so the body streams incrementally in WASM. Without it the browser buffers the whole payload /// before the response stream yields a byte, and the 21.2 read-loop pause backpressures nothing. /// /// The flag is set by SetBrowserResponseStreamingEnabled(true), which records it in /// under the framework key "WebAssemblyEnableStreamingResponse". /// A stub handler reads that option back during SendAsync — the same network-boundary fake the Opus /// format-selection tests use. True network backpressure is browser-only and cannot be unit-profiled; this /// asserts the request is *configured* for streaming, which is the part the harness can observe. Daniel's /// 21.4 manual re-run confirms the actual bounded-memory behaviour. /// /// Both the initial full-stream request (byteOffset 0) and the seek/refill Range request (byteOffset > 0, /// Phase 21.3) flow through , so both are asserted here. /// [TestFixture] public class TrackMediaStreamingEnabledTests { // The framework key SetBrowserResponseStreamingEnabled writes into HttpRequestMessage.Options. private static readonly HttpRequestOptionsKey StreamingOptionKey = new("WebAssemblyEnableStreamingResponse"); // Captures the streaming option off each outgoing request, then returns a minimal 200 with a body so // GetTrackMedia reaches its pass path (ReadAsStreamAsync over ByteArrayContent). private sealed class CapturingHandler : HttpMessageHandler { public bool? StreamingEnabled { get; private set; } protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { StreamingEnabled = request.Options.TryGetValue(StreamingOptionKey, out var enabled) ? enabled : null; var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent("audio-bytes"u8.ToArray()), }; return Task.FromResult(response); } } private sealed class SingleClientFactory : IHttpClientFactory { private readonly HttpMessageHandler _handler; public SingleClientFactory(HttpMessageHandler handler) => _handler = handler; public HttpClient CreateClient(string name) => new(_handler, disposeHandler: false) { BaseAddress = new Uri("https://content.test/") }; } [Test] public async Task GetTrackMedia_InitialStream_EnablesBrowserResponseStreaming() { var handler = new CapturingHandler(); var client = new TrackMediaClient(new SingleClientFactory(handler)); var result = await client.GetTrackMedia("track-1", byteOffset: 0, format: AudioFormat.Lossless); Assert.That(result.Success, Is.True, "the fetch should succeed against the stub"); Assert.That(handler.StreamingEnabled, Is.True, "the initial media stream must enable browser response streaming or the read-loop pause backpressures nothing"); } [Test] public async Task GetTrackMedia_SeekOffsetStream_EnablesBrowserResponseStreaming() { var handler = new CapturingHandler(); var client = new TrackMediaClient(new SingleClientFactory(handler)); var result = await client.GetTrackMedia("track-1", byteOffset: 1_048_576, format: AudioFormat.Opus); Assert.That(result.Success, Is.True, "the offset fetch should succeed against the stub"); Assert.That(handler.StreamingEnabled, Is.True, "the seek/refill Range request must also enable streaming — 21.3 refill depends on the same backpressure"); } }