97 lines
3.1 KiB
Rust
97 lines
3.1 KiB
Rust
//! 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);
|
||
}
|