From dd98cb799433ba7ba43af76a95476d6fa834cb17 Mon Sep 17 00:00:00 2001 From: Jake Date: Wed, 22 Apr 2026 00:36:37 +0100 Subject: [PATCH] fix(A.1 #8): make ResumeUnsupported test actually prove Range header was sent Review feedback: the previous test would pass even if the Range-header logic in download_file were deleted entirely, because File::create truncates the stale .part regardless of which branch set actually_resuming to false. Tightens spawn_no_range_server to return HTTP 400 when the request carries no Range header, and only return 200 + full body when Range is present. A regression that stops sending Range now surfaces as a download failure (empty body from 400, bytes != body assertion) instead of silently passing through the truncation path. --- crates/transcription/src/model_manager.rs | 29 +++++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/crates/transcription/src/model_manager.rs b/crates/transcription/src/model_manager.rs index d6af3bd..aa21d09 100644 --- a/crates/transcription/src/model_manager.rs +++ b/crates/transcription/src/model_manager.rs @@ -350,10 +350,16 @@ mod tests { addr } - /// A minimal HTTP server that always responds with 200 + the full - /// body, even when the request carries a `Range` header. Mirrors a - /// mirror / proxy that strips Range support, exercising the - /// ResumeUnsupported branch in `download_file`. + /// A minimal HTTP server that responds with 200 + full body **iff** + /// the request actually carries a `Range` header, and 400 otherwise. + /// This models a mirror / proxy that accepts Range requests but + /// refuses to honour them (returning a fresh full body), which is + /// exactly the ResumeUnsupported branch `download_file` needs to + /// handle. The 400-on-missing-Range behaviour is load-bearing for + /// the test: it turns "client never sent Range" into a download + /// failure, so deleting the resume-detection logic causes the test + /// to fail rather than pass coincidentally through File::create's + /// truncation semantics. async fn spawn_no_range_server(content: Vec) -> std::net::SocketAddr { let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); let addr = listener.local_addr().unwrap(); @@ -361,7 +367,20 @@ mod tests { tokio::spawn(async move { let (mut socket, _) = listener.accept().await.unwrap(); let mut buf = vec![0u8; 2048]; - let _ = socket.read(&mut buf).await.unwrap(); + let size = socket.read(&mut buf).await.unwrap(); + let request = String::from_utf8_lossy(&buf[..size]).to_lowercase(); + + let saw_range_header = request + .lines() + .any(|line| line.trim_start().starts_with("range:")); + + if !saw_range_header { + let response = "HTTP/1.1 400 Bad Request\r\n\ + Content-Length: 0\r\n\r\n"; + socket.write_all(response.as_bytes()).await.unwrap(); + return; + } + let response = format!( "HTTP/1.1 200 OK\r\n\ Content-Length: {}\r\n\r\n",