//! transport 模块(chunked 解码)的集成测试。 //! Integration tests for the transport module (chunked decoding). use focus_transport::transport::decode_chunked; #[test] fn decodes_simple_chunked_body() { // 两个分块:"Hello" 与 " World",随后是终止分块。 // Two chunks: "Hello" and " World", then terminating chunk. let body = b"5\r\nHello\r\n6\r\n World\r\n0\r\n\r\n"; let decoded = decode_chunked(body).unwrap(); assert_eq!(decoded, b"Hello World"); } #[test] fn decodes_chunk_with_extension() { let body = b"5;name=value\r\nHello\r\n0\r\n\r\n"; let decoded = decode_chunked(body).unwrap(); assert_eq!(decoded, b"Hello"); } #[test] fn decodes_single_chunk() { let body = b"3\r\nabc\r\n0\r\n\r\n"; assert_eq!(decode_chunked(body).unwrap(), b"abc"); } // ---- 增量 chunked 解码器 ---- // ---- incremental chunked decoder ------------------------------------------ use focus_transport::transport::ChunkedDecoder; /// 把所有解码输出合并为一个字符串(测试辅助)。 /// Concatenate all decoded output into one string (test helper). fn drain(dec: &mut ChunkedDecoder) -> String { let mut out = Vec::new(); loop { match dec.take_decoded() { Some(mut chunk) => out.append(&mut chunk), None => { if dec.is_finished() { break; } return String::from_utf8_lossy(&out).to_string(); } } } String::from_utf8_lossy(&out).to_string() } #[test] fn decodes_single_chunk_fed_at_once() { let mut dec = ChunkedDecoder::new(); dec.feed(b"5\r\nhello\r\n0\r\n\r\n"); assert_eq!(drain(&mut dec), "hello"); } #[test] fn decodes_chunk_split_across_feeds() { // 网络分块与 HTTP 分块不对齐:一次喂一半。 // Network chunks misalign with HTTP chunks: feed half at a time. let mut dec = ChunkedDecoder::new(); dec.feed(b"5\r\nhe"); assert_eq!(drain(&mut dec), "he"); dec.feed(b"llo\r\n0\r\n\r\n"); assert_eq!(drain(&mut dec), "llo"); } #[test] fn decodes_multiple_chunks_and_extension() { let mut dec = ChunkedDecoder::new(); dec.feed(b"5;name=value\r\nhello\r\n6\r\n world\r\n0\r\n\r\n"); assert_eq!(drain(&mut dec), "hello world"); } #[test] fn yields_partial_data_before_terminator() { let mut dec = ChunkedDecoder::new(); // 第一个分块完整、第二个分块只喂了部分,应先把已解码部分吐出。 // First chunk complete, second partial: yield decoded bytes so far. dec.feed(b"3\r\nabc\r\n5\r\n12"); assert_eq!(drain(&mut dec), "abc12"); dec.feed(b"345\r\n0\r\n\r\n"); assert_eq!(drain(&mut dec), "345"); } #[test] fn decodes_an_sse_stream_in_chunked_framing() { // 模拟完整 SSE 流(chunked 编码)经解码器逐块吐出。 // Simulate a full SSE stream (chunked-encoded) drained through the decoder. let payload = "event: message_start\r\ndata: {\"type\":\"x\"}\r\n\r\n"; let mut dec = ChunkedDecoder::new(); dec.feed(format!("{:x}\r\n{}\r\n", payload.len(), payload).as_bytes()); dec.feed(b"0\r\n\r\n"); assert_eq!(drain(&mut dec), payload); }