use super::*;
use alloc::vec;
fn f(name: &[u8], value: &[u8]) -> HeaderField {
HeaderField::new(name, value)
}
#[test]
fn rfc_c3_request_sequence_raw() {
let mut enc = HpackEncoder::new();
enc.set_huffman(false);
let mut dec = HpackDecoder::new();
let req1 = [
f(b":method", b"GET"),
f(b":scheme", b"http"),
f(b":path", b"/"),
f(b":authority", b"www.example.com"),
];
let b1 = enc.encode(&req1);
assert_eq!(
b1,
[
0x82, 0x86, 0x84, 0x41, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d
]
);
assert_eq!(dec.decode(&b1).unwrap(), req1);
let req2 = [
f(b":method", b"GET"),
f(b":scheme", b"http"),
f(b":path", b"/"),
f(b":authority", b"www.example.com"),
f(b"cache-control", b"no-cache"),
];
let b2 = enc.encode(&req2);
assert_eq!(
b2,
[
0x82, 0x86, 0x84, 0xbe, 0x58, 0x08, 0x6e, 0x6f, 0x2d, 0x63, 0x61, 0x63, 0x68, 0x65
]
);
assert_eq!(dec.decode(&b2).unwrap(), req2);
let req3 = [
f(b":method", b"GET"),
f(b":scheme", b"https"),
f(b":path", b"/index.html"),
f(b":authority", b"www.example.com"),
f(b"custom-key", b"custom-value"),
];
let b3 = enc.encode(&req3);
assert_eq!(
b3,
[
0x82, 0x87, 0x85, 0xbf, 0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b,
0x65, 0x79, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x76, 0x61, 0x6c, 0x75,
0x65
]
);
assert_eq!(dec.decode(&b3).unwrap(), req3);
}
#[test]
fn rfc_c4_request_sequence_huffman() {
let mut enc = HpackEncoder::new(); let mut dec = HpackDecoder::new();
let req1 = [
f(b":method", b"GET"),
f(b":scheme", b"http"),
f(b":path", b"/"),
f(b":authority", b"www.example.com"),
];
let b1 = enc.encode(&req1);
assert_eq!(
b1,
[
0x82, 0x86, 0x84, 0x41, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab,
0x90, 0xf4, 0xff
]
);
assert_eq!(dec.decode(&b1).unwrap(), req1);
let req2 = [
f(b":method", b"GET"),
f(b":scheme", b"http"),
f(b":path", b"/"),
f(b":authority", b"www.example.com"),
f(b"cache-control", b"no-cache"),
];
let b2 = enc.encode(&req2);
assert_eq!(
b2,
[
0x82, 0x86, 0x84, 0xbe, 0x58, 0x86, 0xa8, 0xeb, 0x10, 0x64, 0x9c, 0xbf
]
);
assert_eq!(dec.decode(&b2).unwrap(), req2);
let req3 = [
f(b":method", b"GET"),
f(b":scheme", b"https"),
f(b":path", b"/index.html"),
f(b":authority", b"www.example.com"),
f(b"custom-key", b"custom-value"),
];
let b3 = enc.encode(&req3);
assert_eq!(
b3,
[
0x82, 0x87, 0x85, 0xbf, 0x40, 0x88, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xa9, 0x7d, 0x7f,
0x89, 0x25, 0xa8, 0x49, 0xe9, 0x5b, 0xb8, 0xe8, 0xb4, 0xbf
]
);
assert_eq!(dec.decode(&b3).unwrap(), req3);
}
#[test]
fn eviction_at_table_size_256() {
let mut enc = HpackEncoder::with_max_table_size(256);
let mut dec = HpackDecoder::with_max_table_size(256);
let resp = [
f(b":status", b"302"),
f(b"cache-control", b"private"),
f(b"date", b"Mon, 21 Oct 2013 20:13:21 GMT"),
f(b"location", b"https://www.example.com"),
];
let block = enc.encode(&resp);
assert_eq!(&block[..3], &[0x3f, 0xe1, 0x01]);
assert_eq!(dec.decode(&block).unwrap(), resp);
assert_eq!(dec.table_max_size(), 256);
let block2 = enc.encode(&resp);
assert_eq!(dec.decode(&block2).unwrap(), resp);
}
#[test]
fn round_trip_many_fields() {
let mut enc = HpackEncoder::new();
let mut dec = HpackDecoder::new();
let fields: vec::Vec<HeaderField> = (0..50)
.map(|i| {
let name = alloc::format!("x-header-{i}");
let val = alloc::format!("value-{}-{}", i, "blahblah".repeat(i % 4));
f(name.as_bytes(), val.as_bytes())
})
.collect();
let block = enc.encode(&fields);
assert_eq!(dec.decode(&block).unwrap(), fields);
}
#[test]
fn sensitive_field_never_indexed() {
let mut enc = HpackEncoder::new();
let mut dec = HpackDecoder::new();
let fields = [HeaderField::sensitive(b"authorization", b"secret-token")];
let block = enc.encode(&fields);
assert_eq!(block[0], 0x1f);
let out = dec.decode(&block).unwrap();
assert_eq!(out, fields);
assert!(out[0].sensitive);
}
#[test]
fn decode_rejects_bad_index() {
let mut dec = HpackDecoder::new();
assert!(matches!(dec.decode(&[0x80]), Err(Error::Corrupt)));
assert!(matches!(dec.decode(&[0xe3]), Err(Error::Corrupt)));
}
#[test]
fn decode_rejects_oversized_size_update() {
let mut dec = HpackDecoder::with_max_table_size(256);
assert!(matches!(
dec.decode(&[0x3f, 0xe1, 0x1f]),
Err(Error::Corrupt)
));
}
#[test]
fn decode_rejects_truncated_string() {
let mut dec = HpackDecoder::new();
assert!(matches!(
dec.decode(&[0x40, 0x05, b'a', b'b']),
Err(Error::UnexpectedEnd)
));
}