#![allow(unused_variables)]
use crate::parser::message::{RequestBuilder, Response};
extern crate alloc;
use alloc::vec;
#[test]
fn test_missing_host_header_enforcement() {
let result = RequestBuilder::new("GET", "/path").build();
assert!(result.is_err(), "Should reject request without Host header");
assert_eq!(result.unwrap_err(), crate::error::ParseError::MissingHostHeader);
}
#[test]
fn test_missing_empty_host_when_no_authority() {
let result = RequestBuilder::new("GET", "/").build();
assert!(result.is_err(), "Should reject request without Host header");
assert_eq!(result.unwrap_err(), crate::error::ParseError::MissingHostHeader);
}
#[test]
fn test_missing_reject_te_in_1xx_response() {
let input = b"HTTP/1.1 100 Continue\r\nTransfer-Encoding: chunked\r\n\r\n";
let result = Response::parse(input);
assert!(result.is_err(), "MISSING: Should reject TE in 1xx responses");
}
#[test]
fn test_missing_reject_te_in_204_response() {
let input = b"HTTP/1.1 204 No Content\r\nTransfer-Encoding: chunked\r\n\r\n";
let result = Response::parse(input);
assert!(result.is_err(), "MISSING: Should reject TE in 204 responses");
}
#[test]
fn test_missing_reject_te_in_2xx_connect_response() {
let input = b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nHello\r\n0\r\n\r\n";
let headers_bytes = vec![(b"Transfer-Encoding".to_vec(), b"chunked".to_vec())];
let result = Response::parse_body(b"5\r\nHello\r\n0\r\n\r\n", &headers_bytes, 200, Some("CONNECT"));
assert!(result.is_ok(), "Should ignore (not reject) TE in 2xx CONNECT responses");
assert!(
result.unwrap().is_empty(),
"2xx CONNECT should have empty body even with TE"
);
}
#[test]
fn test_missing_prevent_bare_cr_in_header_values() {
let result = RequestBuilder::new("GET", "/")
.header("Host", "example.com")
.header("X-Bad", "value\rwith\rCR") .build();
assert!(result.is_err(), "Should reject bare CR in header values");
assert_eq!(
result.unwrap_err(),
crate::error::ParseError::BareCarriageReturnInHeader
);
}
#[test]
fn test_missing_prevent_obs_fold_generation() {
let result = RequestBuilder::new("GET", "/")
.header("Host", "example.com")
.header("X-Bad", "line1\r\n line2") .build();
assert!(result.is_err(), "Should reject obs-fold in header values");
assert_eq!(result.unwrap_err(), crate::error::ParseError::ObsoleteFoldInHeader);
}
#[test]
fn test_missing_no_cl_when_te_present() {
let result = RequestBuilder::new("POST", "/")
.header("Host", "example.com")
.header("Transfer-Encoding", "chunked")
.header("Content-Length", "4") .body(b"test".to_vec())
.build();
assert!(result.is_err(), "Should reject when both TE and CL present");
assert_eq!(result.unwrap_err(), crate::error::ParseError::ConflictingFraming);
}
#[test]
fn test_missing_body_framing_validation() {
let request = RequestBuilder::new("POST", "/")
.header("Host", "example.com")
.header("Content-Length", "4")
.body(b"data".to_vec())
.build();
assert!(request.is_ok(), "Should accept body with Content-Length");
let binding = request.unwrap();
let request_str = core::str::from_utf8(&binding).unwrap();
assert!(request_str.contains("Content-Length:"), "Should have CL");
}
#[test]
fn test_missing_version_check_for_chunked() {
let request = RequestBuilder::new("POST", "/")
.header("Host", "example.com")
.header("Transfer-Encoding", "chunked")
.body(b"5\r\nHello\r\n0\r\n\r\n".to_vec())
.build();
assert!(request.is_ok(), "Should accept chunked with HTTP/1.1");
let binding = request.unwrap();
let request_str = core::str::from_utf8(&binding).unwrap();
assert!(request_str.contains("HTTP/1.1"), "Should use HTTP/1.1");
}
#[test]
fn test_missing_version_check_for_te() {
let input = b"HTTP/1.0 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nHello\r\n0\r\n\r\n";
let result = Response::parse(input);
assert!(result.is_err(), "Should reject TE in HTTP/1.0 responses");
}
#[test]
fn test_missing_no_chunked_in_te_header() {
let result = RequestBuilder::new("GET", "/")
.header("Host", "example.com")
.header("TE", "chunked, gzip") .build();
assert!(result.is_err(), "Should reject 'chunked' in TE header");
assert_eq!(result.unwrap_err(), crate::error::ParseError::ChunkedInTeHeader);
}
#[test]
fn test_missing_te_requires_connection_header() {
let result = RequestBuilder::new("GET", "/")
.header("Host", "example.com")
.header("TE", "gzip") .build();
assert!(result.is_err(), "Should reject TE without Connection: TE");
assert_eq!(result.unwrap_err(), crate::error::ParseError::TeHeaderMissingConnection);
}
#[test]
fn test_missing_absolute_form_support() {
let request = RequestBuilder::new("GET", "http://example.com/path")
.header("Host", "example.com")
.build()
.unwrap();
let request_str = core::str::from_utf8(&request).unwrap();
let uses_absolute_form = request_str.starts_with("GET http://");
assert!(
uses_absolute_form,
"MISSING: Should support absolute-form for proxy requests (currently only origin-form)"
);
}
#[test]
fn test_missing_authority_form_for_connect() {
let request = RequestBuilder::new("CONNECT", "example.com:443")
.header("Host", "example.com:443")
.build()
.unwrap();
let request_str = core::str::from_utf8(&request).unwrap();
let uses_authority_form = request_str.starts_with("CONNECT example.com:443");
assert!(
uses_authority_form,
"MISSING: Should explicitly support authority-form for CONNECT"
);
}
#[test]
fn test_missing_asterisk_form_for_options() {
let request = RequestBuilder::new("OPTIONS", "*")
.header("Host", "example.com")
.build()
.unwrap();
let request_str = core::str::from_utf8(&request).unwrap();
assert!(
request_str.starts_with("OPTIONS *"),
"MISSING: Should explicitly support asterisk-form for OPTIONS"
);
}
#[test]
fn test_missing_comprehensive_request_validation() {
let result = RequestBuilder::new("POST", "/api/data")
.header("X-Custom", "test")
.body(b"payload".to_vec())
.build();
assert!(result.is_err(), "Should reject request without Host header");
assert_eq!(result.unwrap_err(), crate::error::ParseError::MissingHostHeader);
}