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.
This commit is contained in:
2026-04-22 00:36:37 +01:00
parent 6fd38932ce
commit dd98cb7994

View File

@@ -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<u8>) -> 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",