Restructure hpack tests
This commit is contained in:
@@ -540,7 +540,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_sensitive_headers_are_never_indexed() {
|
||||
use http::header::{HeaderName, HeaderValue};
|
||||
use http::header::HeaderValue;
|
||||
|
||||
let name = "my-password".parse().unwrap();
|
||||
let mut value = HeaderValue::try_from_bytes(b"12345").unwrap();
|
||||
|
||||
@@ -146,15 +146,15 @@ mod test {
|
||||
fn encode_single_byte() {
|
||||
let mut dst = Vec::with_capacity(1);
|
||||
|
||||
encode(b"o", &mut dst);
|
||||
encode(b"o", &mut dst).unwrap();
|
||||
assert_eq!(&dst[..], &[0b00111111]);
|
||||
|
||||
dst.clear();
|
||||
encode(b"0", &mut dst);
|
||||
encode(b"0", &mut dst).unwrap();
|
||||
assert_eq!(&dst[..], &[0x0 + 7]);
|
||||
|
||||
dst.clear();
|
||||
encode(b"A", &mut dst);
|
||||
encode(b"A", &mut dst).unwrap();
|
||||
assert_eq!(&dst[..], &[(0x21 << 2) + 3]);
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ mod test {
|
||||
for s in DATA {
|
||||
let mut dst = Vec::with_capacity(s.len());
|
||||
|
||||
encode(s.as_bytes(), &mut dst);
|
||||
encode(s.as_bytes(), &mut dst).unwrap();
|
||||
|
||||
let decoded = decode(&dst).unwrap();
|
||||
|
||||
@@ -187,7 +187,7 @@ mod test {
|
||||
for s in DATA {
|
||||
let mut dst = Vec::with_capacity(s.len());
|
||||
|
||||
encode(s, &mut dst);
|
||||
encode(s, &mut dst).unwrap();
|
||||
|
||||
let decoded = decode(&dst).unwrap();
|
||||
|
||||
|
||||
@@ -516,6 +516,7 @@ impl Table {
|
||||
|
||||
#[cfg(test)]
|
||||
fn assert_valid_state(&self, msg: &'static str) -> bool {
|
||||
/*
|
||||
// Checks that the internal map structure is valid
|
||||
//
|
||||
// Ensure all hash codes in indices match the associated slot
|
||||
@@ -596,6 +597,7 @@ impl Table {
|
||||
assert_eq!(1, cnt, "more than one node pointing here; msg={}", msg);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: Ensure linked lists are correct: no cycles, etc...
|
||||
|
||||
|
||||
596
src/hpack/test/fixture.rs
Normal file
596
src/hpack/test/fixture.rs
Normal file
@@ -0,0 +1,596 @@
|
||||
extern crate bytes;
|
||||
extern crate hex;
|
||||
extern crate serde_json;
|
||||
|
||||
use hpack::{Header, Decoder, Encoder};
|
||||
|
||||
use self::bytes::BytesMut;
|
||||
use self::hex::FromHex;
|
||||
use self::serde_json::Value;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::io::Cursor;
|
||||
use std::path::Path;
|
||||
use std::str;
|
||||
|
||||
fn test_fixture(path: &Path) {
|
||||
let mut file = File::open(path).unwrap();
|
||||
let mut data = String::new();
|
||||
file.read_to_string(&mut data).unwrap();
|
||||
|
||||
let story: Value = serde_json::from_str(&data).unwrap();
|
||||
test_story(story);
|
||||
}
|
||||
|
||||
fn test_story(story: Value) {
|
||||
let story = story.as_object().unwrap();
|
||||
|
||||
if let Some(cases) = story.get("cases") {
|
||||
let mut cases: Vec<_> = cases.as_array().unwrap().iter()
|
||||
.map(|case| {
|
||||
let case = case.as_object().unwrap();
|
||||
|
||||
let size = case.get("header_table_size")
|
||||
.map(|v| v.as_u64().unwrap() as usize);
|
||||
|
||||
let wire = case.get("wire").unwrap().as_str().unwrap();
|
||||
let wire: Vec<u8> = FromHex::from_hex(wire.as_bytes()).unwrap();
|
||||
|
||||
let expect: Vec<_> = case.get("headers").unwrap()
|
||||
.as_array().unwrap().iter()
|
||||
.map(|h| {
|
||||
let h = h.as_object().unwrap();
|
||||
let (name, val) = h.iter().next().unwrap();
|
||||
(name.clone(), val.as_str().unwrap().to_string())
|
||||
})
|
||||
.collect();
|
||||
|
||||
Case {
|
||||
seqno: case.get("seqno").unwrap().as_u64().unwrap(),
|
||||
wire: wire,
|
||||
expect: expect,
|
||||
header_table_size: size,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
cases.sort_by_key(|c| c.seqno);
|
||||
|
||||
let mut decoder = Decoder::default();
|
||||
|
||||
// First, check decoding against the fixtures
|
||||
for case in &cases {
|
||||
let mut expect = case.expect.clone();
|
||||
|
||||
if let Some(size) = case.header_table_size {
|
||||
decoder.queue_size_update(size);
|
||||
}
|
||||
|
||||
decoder.decode(&mut Cursor::new(case.wire.clone().into()), |e| {
|
||||
let (name, value) = expect.remove(0);
|
||||
assert_eq!(name, key_str(&e));
|
||||
assert_eq!(value, value_str(&e));
|
||||
}).unwrap();
|
||||
|
||||
assert_eq!(0, expect.len());
|
||||
}
|
||||
|
||||
let mut encoder = Encoder::default();
|
||||
let mut decoder = Decoder::default();
|
||||
|
||||
// Now, encode the headers
|
||||
for case in &cases {
|
||||
let mut buf = BytesMut::with_capacity(64 * 1024);
|
||||
|
||||
if let Some(size) = case.header_table_size {
|
||||
encoder.update_max_size(size);
|
||||
decoder.queue_size_update(size);
|
||||
}
|
||||
|
||||
let mut input: Vec<_> = case.expect.iter().map(|&(ref name, ref value)| {
|
||||
Header::new(name.clone().into(), value.clone().into()).unwrap().into()
|
||||
}).collect();
|
||||
|
||||
encoder.encode(None, &mut input.clone().into_iter(), &mut buf);
|
||||
|
||||
decoder.decode(&mut Cursor::new(buf.into()), |e| {
|
||||
assert_eq!(e, input.remove(0).reify().unwrap());
|
||||
}).unwrap();
|
||||
|
||||
assert_eq!(0, input.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Case {
|
||||
seqno: u64,
|
||||
wire: Vec<u8>,
|
||||
expect: Vec<(String, String)>,
|
||||
header_table_size: Option<usize>,
|
||||
}
|
||||
|
||||
fn key_str(e: &Header) -> &str {
|
||||
match *e {
|
||||
Header::Field { ref name, .. } => name.as_str(),
|
||||
Header::Authority(..) => ":authority",
|
||||
Header::Method(..) => ":method",
|
||||
Header::Scheme(..) => ":scheme",
|
||||
Header::Path(..) => ":path",
|
||||
Header::Status(..) => ":status",
|
||||
}
|
||||
}
|
||||
|
||||
fn value_str(e: &Header) -> &str {
|
||||
match *e {
|
||||
Header::Field { ref value, .. } => value.to_str().unwrap(),
|
||||
Header::Authority(ref v) => &**v,
|
||||
Header::Method(ref m) => m.as_str(),
|
||||
Header::Scheme(ref v) => &**v,
|
||||
Header::Path(ref v) => &**v,
|
||||
Header::Status(ref v) => v.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! fixture_mod {
|
||||
($module:ident => {
|
||||
$(
|
||||
($fn:ident, $path:expr);
|
||||
)+
|
||||
}) => {
|
||||
mod $module {
|
||||
$(
|
||||
#[test]
|
||||
fn $fn() {
|
||||
let path = ::std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("fixtures/hpack")
|
||||
.join($path);
|
||||
|
||||
super::test_fixture(path.as_ref());
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixture_mod!(
|
||||
haskell_http2_linear_huffman => {
|
||||
(story_00, "haskell-http2-linear-huffman/story_00.json");
|
||||
(story_01, "haskell-http2-linear-huffman/story_01.json");
|
||||
(story_02, "haskell-http2-linear-huffman/story_02.json");
|
||||
(story_03, "haskell-http2-linear-huffman/story_03.json");
|
||||
(story_04, "haskell-http2-linear-huffman/story_04.json");
|
||||
(story_05, "haskell-http2-linear-huffman/story_05.json");
|
||||
(story_06, "haskell-http2-linear-huffman/story_06.json");
|
||||
(story_07, "haskell-http2-linear-huffman/story_07.json");
|
||||
(story_08, "haskell-http2-linear-huffman/story_08.json");
|
||||
(story_09, "haskell-http2-linear-huffman/story_09.json");
|
||||
(story_10, "haskell-http2-linear-huffman/story_10.json");
|
||||
(story_11, "haskell-http2-linear-huffman/story_11.json");
|
||||
(story_12, "haskell-http2-linear-huffman/story_12.json");
|
||||
(story_13, "haskell-http2-linear-huffman/story_13.json");
|
||||
(story_14, "haskell-http2-linear-huffman/story_14.json");
|
||||
(story_15, "haskell-http2-linear-huffman/story_15.json");
|
||||
(story_16, "haskell-http2-linear-huffman/story_16.json");
|
||||
(story_17, "haskell-http2-linear-huffman/story_17.json");
|
||||
(story_18, "haskell-http2-linear-huffman/story_18.json");
|
||||
(story_19, "haskell-http2-linear-huffman/story_19.json");
|
||||
(story_20, "haskell-http2-linear-huffman/story_20.json");
|
||||
(story_21, "haskell-http2-linear-huffman/story_21.json");
|
||||
(story_22, "haskell-http2-linear-huffman/story_22.json");
|
||||
(story_23, "haskell-http2-linear-huffman/story_23.json");
|
||||
(story_24, "haskell-http2-linear-huffman/story_24.json");
|
||||
(story_25, "haskell-http2-linear-huffman/story_25.json");
|
||||
(story_26, "haskell-http2-linear-huffman/story_26.json");
|
||||
(story_27, "haskell-http2-linear-huffman/story_27.json");
|
||||
(story_28, "haskell-http2-linear-huffman/story_28.json");
|
||||
(story_29, "haskell-http2-linear-huffman/story_29.json");
|
||||
(story_30, "haskell-http2-linear-huffman/story_30.json");
|
||||
(story_31, "haskell-http2-linear-huffman/story_31.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
python_hpack => {
|
||||
(story_00, "python-hpack/story_00.json");
|
||||
(story_01, "python-hpack/story_01.json");
|
||||
(story_02, "python-hpack/story_02.json");
|
||||
(story_03, "python-hpack/story_03.json");
|
||||
(story_04, "python-hpack/story_04.json");
|
||||
(story_05, "python-hpack/story_05.json");
|
||||
(story_06, "python-hpack/story_06.json");
|
||||
(story_07, "python-hpack/story_07.json");
|
||||
(story_08, "python-hpack/story_08.json");
|
||||
(story_09, "python-hpack/story_09.json");
|
||||
(story_10, "python-hpack/story_10.json");
|
||||
(story_11, "python-hpack/story_11.json");
|
||||
(story_12, "python-hpack/story_12.json");
|
||||
(story_13, "python-hpack/story_13.json");
|
||||
(story_14, "python-hpack/story_14.json");
|
||||
(story_15, "python-hpack/story_15.json");
|
||||
(story_16, "python-hpack/story_16.json");
|
||||
(story_17, "python-hpack/story_17.json");
|
||||
(story_18, "python-hpack/story_18.json");
|
||||
(story_19, "python-hpack/story_19.json");
|
||||
(story_20, "python-hpack/story_20.json");
|
||||
(story_21, "python-hpack/story_21.json");
|
||||
(story_22, "python-hpack/story_22.json");
|
||||
(story_23, "python-hpack/story_23.json");
|
||||
(story_24, "python-hpack/story_24.json");
|
||||
(story_25, "python-hpack/story_25.json");
|
||||
(story_26, "python-hpack/story_26.json");
|
||||
(story_27, "python-hpack/story_27.json");
|
||||
(story_28, "python-hpack/story_28.json");
|
||||
(story_29, "python-hpack/story_29.json");
|
||||
(story_30, "python-hpack/story_30.json");
|
||||
(story_31, "python-hpack/story_31.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
nghttp2_16384_4096 => {
|
||||
(story_00, "nghttp2-16384-4096/story_00.json");
|
||||
(story_01, "nghttp2-16384-4096/story_01.json");
|
||||
(story_02, "nghttp2-16384-4096/story_02.json");
|
||||
(story_03, "nghttp2-16384-4096/story_03.json");
|
||||
(story_04, "nghttp2-16384-4096/story_04.json");
|
||||
(story_05, "nghttp2-16384-4096/story_05.json");
|
||||
(story_06, "nghttp2-16384-4096/story_06.json");
|
||||
(story_07, "nghttp2-16384-4096/story_07.json");
|
||||
(story_08, "nghttp2-16384-4096/story_08.json");
|
||||
(story_09, "nghttp2-16384-4096/story_09.json");
|
||||
(story_10, "nghttp2-16384-4096/story_10.json");
|
||||
(story_11, "nghttp2-16384-4096/story_11.json");
|
||||
(story_12, "nghttp2-16384-4096/story_12.json");
|
||||
(story_13, "nghttp2-16384-4096/story_13.json");
|
||||
(story_14, "nghttp2-16384-4096/story_14.json");
|
||||
(story_15, "nghttp2-16384-4096/story_15.json");
|
||||
(story_16, "nghttp2-16384-4096/story_16.json");
|
||||
(story_17, "nghttp2-16384-4096/story_17.json");
|
||||
(story_18, "nghttp2-16384-4096/story_18.json");
|
||||
(story_19, "nghttp2-16384-4096/story_19.json");
|
||||
(story_20, "nghttp2-16384-4096/story_20.json");
|
||||
(story_21, "nghttp2-16384-4096/story_21.json");
|
||||
(story_22, "nghttp2-16384-4096/story_22.json");
|
||||
(story_23, "nghttp2-16384-4096/story_23.json");
|
||||
(story_24, "nghttp2-16384-4096/story_24.json");
|
||||
(story_25, "nghttp2-16384-4096/story_25.json");
|
||||
(story_26, "nghttp2-16384-4096/story_26.json");
|
||||
(story_27, "nghttp2-16384-4096/story_27.json");
|
||||
(story_28, "nghttp2-16384-4096/story_28.json");
|
||||
(story_29, "nghttp2-16384-4096/story_29.json");
|
||||
(story_30, "nghttp2-16384-4096/story_30.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
node_http2_hpack => {
|
||||
(story_00, "node-http2-hpack/story_00.json");
|
||||
(story_01, "node-http2-hpack/story_01.json");
|
||||
(story_02, "node-http2-hpack/story_02.json");
|
||||
(story_03, "node-http2-hpack/story_03.json");
|
||||
(story_04, "node-http2-hpack/story_04.json");
|
||||
(story_05, "node-http2-hpack/story_05.json");
|
||||
(story_06, "node-http2-hpack/story_06.json");
|
||||
(story_07, "node-http2-hpack/story_07.json");
|
||||
(story_08, "node-http2-hpack/story_08.json");
|
||||
(story_09, "node-http2-hpack/story_09.json");
|
||||
(story_10, "node-http2-hpack/story_10.json");
|
||||
(story_11, "node-http2-hpack/story_11.json");
|
||||
(story_12, "node-http2-hpack/story_12.json");
|
||||
(story_13, "node-http2-hpack/story_13.json");
|
||||
(story_14, "node-http2-hpack/story_14.json");
|
||||
(story_15, "node-http2-hpack/story_15.json");
|
||||
(story_16, "node-http2-hpack/story_16.json");
|
||||
(story_17, "node-http2-hpack/story_17.json");
|
||||
(story_18, "node-http2-hpack/story_18.json");
|
||||
(story_19, "node-http2-hpack/story_19.json");
|
||||
(story_20, "node-http2-hpack/story_20.json");
|
||||
(story_21, "node-http2-hpack/story_21.json");
|
||||
(story_22, "node-http2-hpack/story_22.json");
|
||||
(story_23, "node-http2-hpack/story_23.json");
|
||||
(story_24, "node-http2-hpack/story_24.json");
|
||||
(story_25, "node-http2-hpack/story_25.json");
|
||||
(story_26, "node-http2-hpack/story_26.json");
|
||||
(story_27, "node-http2-hpack/story_27.json");
|
||||
(story_28, "node-http2-hpack/story_28.json");
|
||||
(story_29, "node-http2-hpack/story_29.json");
|
||||
(story_30, "node-http2-hpack/story_30.json");
|
||||
(story_31, "node-http2-hpack/story_31.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
nghttp2_change_table_size => {
|
||||
(story_00, "nghttp2-change-table-size/story_00.json");
|
||||
(story_01, "nghttp2-change-table-size/story_01.json");
|
||||
(story_02, "nghttp2-change-table-size/story_02.json");
|
||||
(story_03, "nghttp2-change-table-size/story_03.json");
|
||||
(story_04, "nghttp2-change-table-size/story_04.json");
|
||||
(story_05, "nghttp2-change-table-size/story_05.json");
|
||||
(story_06, "nghttp2-change-table-size/story_06.json");
|
||||
(story_07, "nghttp2-change-table-size/story_07.json");
|
||||
(story_08, "nghttp2-change-table-size/story_08.json");
|
||||
(story_09, "nghttp2-change-table-size/story_09.json");
|
||||
(story_10, "nghttp2-change-table-size/story_10.json");
|
||||
(story_11, "nghttp2-change-table-size/story_11.json");
|
||||
(story_12, "nghttp2-change-table-size/story_12.json");
|
||||
(story_13, "nghttp2-change-table-size/story_13.json");
|
||||
(story_14, "nghttp2-change-table-size/story_14.json");
|
||||
(story_15, "nghttp2-change-table-size/story_15.json");
|
||||
(story_16, "nghttp2-change-table-size/story_16.json");
|
||||
(story_17, "nghttp2-change-table-size/story_17.json");
|
||||
(story_18, "nghttp2-change-table-size/story_18.json");
|
||||
(story_19, "nghttp2-change-table-size/story_19.json");
|
||||
(story_20, "nghttp2-change-table-size/story_20.json");
|
||||
(story_21, "nghttp2-change-table-size/story_21.json");
|
||||
(story_22, "nghttp2-change-table-size/story_22.json");
|
||||
(story_23, "nghttp2-change-table-size/story_23.json");
|
||||
(story_24, "nghttp2-change-table-size/story_24.json");
|
||||
(story_25, "nghttp2-change-table-size/story_25.json");
|
||||
(story_26, "nghttp2-change-table-size/story_26.json");
|
||||
(story_27, "nghttp2-change-table-size/story_27.json");
|
||||
(story_28, "nghttp2-change-table-size/story_28.json");
|
||||
(story_29, "nghttp2-change-table-size/story_29.json");
|
||||
(story_30, "nghttp2-change-table-size/story_30.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
haskell_http2_static_huffman => {
|
||||
(story_00, "haskell-http2-static-huffman/story_00.json");
|
||||
(story_01, "haskell-http2-static-huffman/story_01.json");
|
||||
(story_02, "haskell-http2-static-huffman/story_02.json");
|
||||
(story_03, "haskell-http2-static-huffman/story_03.json");
|
||||
(story_04, "haskell-http2-static-huffman/story_04.json");
|
||||
(story_05, "haskell-http2-static-huffman/story_05.json");
|
||||
(story_06, "haskell-http2-static-huffman/story_06.json");
|
||||
(story_07, "haskell-http2-static-huffman/story_07.json");
|
||||
(story_08, "haskell-http2-static-huffman/story_08.json");
|
||||
(story_09, "haskell-http2-static-huffman/story_09.json");
|
||||
(story_10, "haskell-http2-static-huffman/story_10.json");
|
||||
(story_11, "haskell-http2-static-huffman/story_11.json");
|
||||
(story_12, "haskell-http2-static-huffman/story_12.json");
|
||||
(story_13, "haskell-http2-static-huffman/story_13.json");
|
||||
(story_14, "haskell-http2-static-huffman/story_14.json");
|
||||
(story_15, "haskell-http2-static-huffman/story_15.json");
|
||||
(story_16, "haskell-http2-static-huffman/story_16.json");
|
||||
(story_17, "haskell-http2-static-huffman/story_17.json");
|
||||
(story_18, "haskell-http2-static-huffman/story_18.json");
|
||||
(story_19, "haskell-http2-static-huffman/story_19.json");
|
||||
(story_20, "haskell-http2-static-huffman/story_20.json");
|
||||
(story_21, "haskell-http2-static-huffman/story_21.json");
|
||||
(story_22, "haskell-http2-static-huffman/story_22.json");
|
||||
(story_23, "haskell-http2-static-huffman/story_23.json");
|
||||
(story_24, "haskell-http2-static-huffman/story_24.json");
|
||||
(story_25, "haskell-http2-static-huffman/story_25.json");
|
||||
(story_26, "haskell-http2-static-huffman/story_26.json");
|
||||
(story_27, "haskell-http2-static-huffman/story_27.json");
|
||||
(story_28, "haskell-http2-static-huffman/story_28.json");
|
||||
(story_29, "haskell-http2-static-huffman/story_29.json");
|
||||
(story_30, "haskell-http2-static-huffman/story_30.json");
|
||||
(story_31, "haskell-http2-static-huffman/story_31.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
haskell_http2_naive_huffman => {
|
||||
(story_00, "haskell-http2-naive-huffman/story_00.json");
|
||||
(story_01, "haskell-http2-naive-huffman/story_01.json");
|
||||
(story_02, "haskell-http2-naive-huffman/story_02.json");
|
||||
(story_03, "haskell-http2-naive-huffman/story_03.json");
|
||||
(story_04, "haskell-http2-naive-huffman/story_04.json");
|
||||
(story_05, "haskell-http2-naive-huffman/story_05.json");
|
||||
(story_06, "haskell-http2-naive-huffman/story_06.json");
|
||||
(story_07, "haskell-http2-naive-huffman/story_07.json");
|
||||
(story_08, "haskell-http2-naive-huffman/story_08.json");
|
||||
(story_09, "haskell-http2-naive-huffman/story_09.json");
|
||||
(story_10, "haskell-http2-naive-huffman/story_10.json");
|
||||
(story_11, "haskell-http2-naive-huffman/story_11.json");
|
||||
(story_12, "haskell-http2-naive-huffman/story_12.json");
|
||||
(story_13, "haskell-http2-naive-huffman/story_13.json");
|
||||
(story_14, "haskell-http2-naive-huffman/story_14.json");
|
||||
(story_15, "haskell-http2-naive-huffman/story_15.json");
|
||||
(story_16, "haskell-http2-naive-huffman/story_16.json");
|
||||
(story_17, "haskell-http2-naive-huffman/story_17.json");
|
||||
(story_18, "haskell-http2-naive-huffman/story_18.json");
|
||||
(story_19, "haskell-http2-naive-huffman/story_19.json");
|
||||
(story_20, "haskell-http2-naive-huffman/story_20.json");
|
||||
(story_21, "haskell-http2-naive-huffman/story_21.json");
|
||||
(story_22, "haskell-http2-naive-huffman/story_22.json");
|
||||
(story_23, "haskell-http2-naive-huffman/story_23.json");
|
||||
(story_24, "haskell-http2-naive-huffman/story_24.json");
|
||||
(story_25, "haskell-http2-naive-huffman/story_25.json");
|
||||
(story_26, "haskell-http2-naive-huffman/story_26.json");
|
||||
(story_27, "haskell-http2-naive-huffman/story_27.json");
|
||||
(story_28, "haskell-http2-naive-huffman/story_28.json");
|
||||
(story_29, "haskell-http2-naive-huffman/story_29.json");
|
||||
(story_30, "haskell-http2-naive-huffman/story_30.json");
|
||||
(story_31, "haskell-http2-naive-huffman/story_31.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
haskell_http2_naive => {
|
||||
(story_00, "haskell-http2-naive/story_00.json");
|
||||
(story_01, "haskell-http2-naive/story_01.json");
|
||||
(story_02, "haskell-http2-naive/story_02.json");
|
||||
(story_03, "haskell-http2-naive/story_03.json");
|
||||
(story_04, "haskell-http2-naive/story_04.json");
|
||||
(story_05, "haskell-http2-naive/story_05.json");
|
||||
(story_06, "haskell-http2-naive/story_06.json");
|
||||
(story_07, "haskell-http2-naive/story_07.json");
|
||||
(story_08, "haskell-http2-naive/story_08.json");
|
||||
(story_09, "haskell-http2-naive/story_09.json");
|
||||
(story_10, "haskell-http2-naive/story_10.json");
|
||||
(story_11, "haskell-http2-naive/story_11.json");
|
||||
(story_12, "haskell-http2-naive/story_12.json");
|
||||
(story_13, "haskell-http2-naive/story_13.json");
|
||||
(story_14, "haskell-http2-naive/story_14.json");
|
||||
(story_15, "haskell-http2-naive/story_15.json");
|
||||
(story_16, "haskell-http2-naive/story_16.json");
|
||||
(story_17, "haskell-http2-naive/story_17.json");
|
||||
(story_18, "haskell-http2-naive/story_18.json");
|
||||
(story_19, "haskell-http2-naive/story_19.json");
|
||||
(story_20, "haskell-http2-naive/story_20.json");
|
||||
(story_21, "haskell-http2-naive/story_21.json");
|
||||
(story_22, "haskell-http2-naive/story_22.json");
|
||||
(story_23, "haskell-http2-naive/story_23.json");
|
||||
(story_24, "haskell-http2-naive/story_24.json");
|
||||
(story_25, "haskell-http2-naive/story_25.json");
|
||||
(story_26, "haskell-http2-naive/story_26.json");
|
||||
(story_27, "haskell-http2-naive/story_27.json");
|
||||
(story_28, "haskell-http2-naive/story_28.json");
|
||||
(story_29, "haskell-http2-naive/story_29.json");
|
||||
(story_30, "haskell-http2-naive/story_30.json");
|
||||
(story_31, "haskell-http2-naive/story_31.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
haskell_http2_static => {
|
||||
(story_00, "haskell-http2-static/story_00.json");
|
||||
(story_01, "haskell-http2-static/story_01.json");
|
||||
(story_02, "haskell-http2-static/story_02.json");
|
||||
(story_03, "haskell-http2-static/story_03.json");
|
||||
(story_04, "haskell-http2-static/story_04.json");
|
||||
(story_05, "haskell-http2-static/story_05.json");
|
||||
(story_06, "haskell-http2-static/story_06.json");
|
||||
(story_07, "haskell-http2-static/story_07.json");
|
||||
(story_08, "haskell-http2-static/story_08.json");
|
||||
(story_09, "haskell-http2-static/story_09.json");
|
||||
(story_10, "haskell-http2-static/story_10.json");
|
||||
(story_11, "haskell-http2-static/story_11.json");
|
||||
(story_12, "haskell-http2-static/story_12.json");
|
||||
(story_13, "haskell-http2-static/story_13.json");
|
||||
(story_14, "haskell-http2-static/story_14.json");
|
||||
(story_15, "haskell-http2-static/story_15.json");
|
||||
(story_16, "haskell-http2-static/story_16.json");
|
||||
(story_17, "haskell-http2-static/story_17.json");
|
||||
(story_18, "haskell-http2-static/story_18.json");
|
||||
(story_19, "haskell-http2-static/story_19.json");
|
||||
(story_20, "haskell-http2-static/story_20.json");
|
||||
(story_21, "haskell-http2-static/story_21.json");
|
||||
(story_22, "haskell-http2-static/story_22.json");
|
||||
(story_23, "haskell-http2-static/story_23.json");
|
||||
(story_24, "haskell-http2-static/story_24.json");
|
||||
(story_25, "haskell-http2-static/story_25.json");
|
||||
(story_26, "haskell-http2-static/story_26.json");
|
||||
(story_27, "haskell-http2-static/story_27.json");
|
||||
(story_28, "haskell-http2-static/story_28.json");
|
||||
(story_29, "haskell-http2-static/story_29.json");
|
||||
(story_30, "haskell-http2-static/story_30.json");
|
||||
(story_31, "haskell-http2-static/story_31.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
nghttp2 => {
|
||||
(story_00, "nghttp2/story_00.json");
|
||||
(story_01, "nghttp2/story_01.json");
|
||||
(story_02, "nghttp2/story_02.json");
|
||||
(story_03, "nghttp2/story_03.json");
|
||||
(story_04, "nghttp2/story_04.json");
|
||||
(story_05, "nghttp2/story_05.json");
|
||||
(story_06, "nghttp2/story_06.json");
|
||||
(story_07, "nghttp2/story_07.json");
|
||||
(story_08, "nghttp2/story_08.json");
|
||||
(story_09, "nghttp2/story_09.json");
|
||||
(story_10, "nghttp2/story_10.json");
|
||||
(story_11, "nghttp2/story_11.json");
|
||||
(story_12, "nghttp2/story_12.json");
|
||||
(story_13, "nghttp2/story_13.json");
|
||||
(story_14, "nghttp2/story_14.json");
|
||||
(story_15, "nghttp2/story_15.json");
|
||||
(story_16, "nghttp2/story_16.json");
|
||||
(story_17, "nghttp2/story_17.json");
|
||||
(story_18, "nghttp2/story_18.json");
|
||||
(story_19, "nghttp2/story_19.json");
|
||||
(story_20, "nghttp2/story_20.json");
|
||||
(story_21, "nghttp2/story_21.json");
|
||||
(story_22, "nghttp2/story_22.json");
|
||||
(story_23, "nghttp2/story_23.json");
|
||||
(story_24, "nghttp2/story_24.json");
|
||||
(story_25, "nghttp2/story_25.json");
|
||||
(story_26, "nghttp2/story_26.json");
|
||||
(story_27, "nghttp2/story_27.json");
|
||||
(story_28, "nghttp2/story_28.json");
|
||||
(story_29, "nghttp2/story_29.json");
|
||||
(story_30, "nghttp2/story_30.json");
|
||||
(story_31, "nghttp2/story_31.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
haskell_http2_linear => {
|
||||
(story_00, "haskell-http2-linear/story_00.json");
|
||||
(story_01, "haskell-http2-linear/story_01.json");
|
||||
(story_02, "haskell-http2-linear/story_02.json");
|
||||
(story_03, "haskell-http2-linear/story_03.json");
|
||||
(story_04, "haskell-http2-linear/story_04.json");
|
||||
(story_05, "haskell-http2-linear/story_05.json");
|
||||
(story_06, "haskell-http2-linear/story_06.json");
|
||||
(story_07, "haskell-http2-linear/story_07.json");
|
||||
(story_08, "haskell-http2-linear/story_08.json");
|
||||
(story_09, "haskell-http2-linear/story_09.json");
|
||||
(story_10, "haskell-http2-linear/story_10.json");
|
||||
(story_11, "haskell-http2-linear/story_11.json");
|
||||
(story_12, "haskell-http2-linear/story_12.json");
|
||||
(story_13, "haskell-http2-linear/story_13.json");
|
||||
(story_14, "haskell-http2-linear/story_14.json");
|
||||
(story_15, "haskell-http2-linear/story_15.json");
|
||||
(story_16, "haskell-http2-linear/story_16.json");
|
||||
(story_17, "haskell-http2-linear/story_17.json");
|
||||
(story_18, "haskell-http2-linear/story_18.json");
|
||||
(story_19, "haskell-http2-linear/story_19.json");
|
||||
(story_20, "haskell-http2-linear/story_20.json");
|
||||
(story_21, "haskell-http2-linear/story_21.json");
|
||||
(story_22, "haskell-http2-linear/story_22.json");
|
||||
(story_23, "haskell-http2-linear/story_23.json");
|
||||
(story_24, "haskell-http2-linear/story_24.json");
|
||||
(story_25, "haskell-http2-linear/story_25.json");
|
||||
(story_26, "haskell-http2-linear/story_26.json");
|
||||
(story_27, "haskell-http2-linear/story_27.json");
|
||||
(story_28, "haskell-http2-linear/story_28.json");
|
||||
(story_29, "haskell-http2-linear/story_29.json");
|
||||
(story_30, "haskell-http2-linear/story_30.json");
|
||||
(story_31, "haskell-http2-linear/story_31.json");
|
||||
}
|
||||
);
|
||||
|
||||
fixture_mod!(
|
||||
go_hpack => {
|
||||
(story_00, "go-hpack/story_00.json");
|
||||
(story_01, "go-hpack/story_01.json");
|
||||
(story_02, "go-hpack/story_02.json");
|
||||
(story_03, "go-hpack/story_03.json");
|
||||
(story_04, "go-hpack/story_04.json");
|
||||
(story_05, "go-hpack/story_05.json");
|
||||
(story_06, "go-hpack/story_06.json");
|
||||
(story_07, "go-hpack/story_07.json");
|
||||
(story_08, "go-hpack/story_08.json");
|
||||
(story_09, "go-hpack/story_09.json");
|
||||
(story_10, "go-hpack/story_10.json");
|
||||
(story_11, "go-hpack/story_11.json");
|
||||
(story_12, "go-hpack/story_12.json");
|
||||
(story_13, "go-hpack/story_13.json");
|
||||
(story_14, "go-hpack/story_14.json");
|
||||
(story_15, "go-hpack/story_15.json");
|
||||
(story_16, "go-hpack/story_16.json");
|
||||
(story_17, "go-hpack/story_17.json");
|
||||
(story_18, "go-hpack/story_18.json");
|
||||
(story_19, "go-hpack/story_19.json");
|
||||
(story_20, "go-hpack/story_20.json");
|
||||
(story_21, "go-hpack/story_21.json");
|
||||
(story_22, "go-hpack/story_22.json");
|
||||
(story_23, "go-hpack/story_23.json");
|
||||
(story_24, "go-hpack/story_24.json");
|
||||
(story_25, "go-hpack/story_25.json");
|
||||
(story_26, "go-hpack/story_26.json");
|
||||
(story_27, "go-hpack/story_27.json");
|
||||
(story_28, "go-hpack/story_28.json");
|
||||
(story_29, "go-hpack/story_29.json");
|
||||
(story_30, "go-hpack/story_30.json");
|
||||
(story_31, "go-hpack/story_31.json");
|
||||
}
|
||||
);
|
||||
@@ -1,87 +1,19 @@
|
||||
extern crate bytes;
|
||||
extern crate hex;
|
||||
extern crate walkdir;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate quickcheck;
|
||||
extern crate rand;
|
||||
|
||||
use super::{Header, Decoder, Encoder, Encode};
|
||||
use hpack::{Header, Decoder, Encoder, Encode};
|
||||
|
||||
use http::header::{HeaderName, HeaderValue};
|
||||
|
||||
use self::bytes::BytesMut;
|
||||
use self::hex::FromHex;
|
||||
use self::serde_json::Value;
|
||||
use self::walkdir::WalkDir;
|
||||
use self::quickcheck::{QuickCheck, Arbitrary, Gen, TestResult};
|
||||
use self::rand::{StdRng, Rng, SeedableRng};
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::io::Cursor;
|
||||
use std::path::Path;
|
||||
use std::str;
|
||||
|
||||
const MAX_CHUNK: usize = 2 * 1024;
|
||||
|
||||
#[test]
|
||||
fn hpack_failing_1() {
|
||||
FuzzHpack::new_reduced([
|
||||
14571479824075392697, 1933795017656710260, 3334564825787790363, 18384038562943935004,
|
||||
], 100).run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hpack_failing_2() {
|
||||
FuzzHpack::new_reduced([
|
||||
93927840931624528, 7252171548136134810, 13289640692556535960, 11484086244506193733,
|
||||
], 100).run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hpack_failing_3() {
|
||||
FuzzHpack::new_reduced([
|
||||
4320463360720445614, 7244328615656028238, 10856862580207993426, 5400459931473084625,
|
||||
], 61).run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hpack_failing_4() {
|
||||
FuzzHpack::new_reduced([
|
||||
7199712575090753518, 8301132414711594706, 8069319383349578021, 5376546610900316263,
|
||||
], 107).run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hpack_failing_5() {
|
||||
FuzzHpack::new_reduced([
|
||||
17764083779960581082, 12579311332935512090, 16627815831742045696, 13140603923739395199,
|
||||
], 101).run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hpack_failing_6() {
|
||||
FuzzHpack::new_reduced([
|
||||
7970045195656406858, 7319095306567062282, 8226114865494971289, 10649653503082373659,
|
||||
], 147).run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hpack_failing_7() {
|
||||
FuzzHpack::new_reduced([
|
||||
7990149962280599924, 6223290743332495022, 5461160958499241043, 157399552951946949,
|
||||
], 31).run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hpack_failing_8() {
|
||||
FuzzHpack::new_reduced([
|
||||
5719253325816917205, 15546677577651198340, 11565363105171925122, 12844885905471928303,
|
||||
], 110).run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hpack_fuzz() {
|
||||
fn prop(fuzz: FuzzHpack) -> TestResult {
|
||||
@@ -116,10 +48,6 @@ struct HeaderFrame {
|
||||
}
|
||||
|
||||
impl FuzzHpack {
|
||||
fn new_reduced(seed: [usize; 4], i: usize) -> FuzzHpack {
|
||||
FuzzHpack::new(seed)
|
||||
}
|
||||
|
||||
fn new(seed: [usize; 4]) -> FuzzHpack {
|
||||
// Seed the RNG
|
||||
let mut rng = StdRng::from_seed(&seed);
|
||||
@@ -188,9 +116,9 @@ impl FuzzHpack {
|
||||
}
|
||||
}
|
||||
|
||||
fn run(mut self) {
|
||||
fn run(self) {
|
||||
let mut chunks = self.chunks;
|
||||
let mut frames = self.frames;
|
||||
let frames = self.frames;
|
||||
let mut expect = vec![];
|
||||
|
||||
let mut encoder = Encoder::default();
|
||||
@@ -418,156 +346,3 @@ fn gen_string(g: &mut StdRng, min: usize, max: usize) -> String {
|
||||
|
||||
String::from_utf8(bytes).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hpack_fixtures() {
|
||||
let fixture_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("fixtures/hpack");
|
||||
|
||||
for entry in WalkDir::new(fixture_dir) {
|
||||
let entry = entry.unwrap();
|
||||
let path = entry.path().to_str().unwrap();
|
||||
|
||||
if !path.ends_with(".json") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if path.contains("raw-data") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(filter) = env::var("HPACK_FIXTURE_FILTER").ok() {
|
||||
if !path.contains(&filter) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
println!("");
|
||||
println!("");
|
||||
println!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
println!("~~~ {:?} ~~~", entry.path());
|
||||
println!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
println!("");
|
||||
println!("");
|
||||
|
||||
test_fixture(entry.path());
|
||||
}
|
||||
}
|
||||
|
||||
fn test_fixture(path: &Path) {
|
||||
let mut file = File::open(path).unwrap();
|
||||
let mut data = String::new();
|
||||
file.read_to_string(&mut data).unwrap();
|
||||
|
||||
let story: Value = serde_json::from_str(&data).unwrap();
|
||||
test_story(story);
|
||||
}
|
||||
|
||||
fn test_story(story: Value) {
|
||||
let story = story.as_object().unwrap();
|
||||
|
||||
if let Some(cases) = story.get("cases") {
|
||||
let mut cases: Vec<_> = cases.as_array().unwrap().iter()
|
||||
.map(|case| {
|
||||
let case = case.as_object().unwrap();
|
||||
|
||||
let size = case.get("header_table_size")
|
||||
.map(|v| v.as_u64().unwrap() as usize);
|
||||
|
||||
let wire = case.get("wire").unwrap().as_str().unwrap();
|
||||
let wire: Vec<u8> = FromHex::from_hex(wire.as_bytes()).unwrap();
|
||||
|
||||
let mut expect: Vec<_> = case.get("headers").unwrap()
|
||||
.as_array().unwrap().iter()
|
||||
.map(|h| {
|
||||
let h = h.as_object().unwrap();
|
||||
let (name, val) = h.iter().next().unwrap();
|
||||
(name.clone(), val.as_str().unwrap().to_string())
|
||||
})
|
||||
.collect();
|
||||
|
||||
Case {
|
||||
seqno: case.get("seqno").unwrap().as_u64().unwrap(),
|
||||
wire: wire,
|
||||
expect: expect,
|
||||
header_table_size: size,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
cases.sort_by_key(|c| c.seqno);
|
||||
|
||||
let mut decoder = Decoder::default();
|
||||
|
||||
// First, check decoding against the fixtures
|
||||
for case in &cases {
|
||||
let mut expect = case.expect.clone();
|
||||
|
||||
if let Some(size) = case.header_table_size {
|
||||
decoder.queue_size_update(size);
|
||||
}
|
||||
|
||||
decoder.decode(&mut Cursor::new(case.wire.clone().into()), |e| {
|
||||
let (name, value) = expect.remove(0);
|
||||
assert_eq!(name, key_str(&e));
|
||||
assert_eq!(value, value_str(&e));
|
||||
}).unwrap();
|
||||
|
||||
assert_eq!(0, expect.len());
|
||||
}
|
||||
|
||||
let mut encoder = Encoder::default();
|
||||
let mut decoder = Decoder::default();
|
||||
|
||||
// Now, encode the headers
|
||||
for case in &cases {
|
||||
let mut buf = BytesMut::with_capacity(64 * 1024);
|
||||
|
||||
if let Some(size) = case.header_table_size {
|
||||
encoder.update_max_size(size);
|
||||
decoder.queue_size_update(size);
|
||||
}
|
||||
|
||||
let mut input: Vec<_> = case.expect.iter().map(|&(ref name, ref value)| {
|
||||
Header::new(name.clone().into(), value.clone().into()).unwrap().into()
|
||||
}).collect();
|
||||
|
||||
encoder.encode(None, &mut input.clone().into_iter(), &mut buf);
|
||||
|
||||
decoder.decode(&mut Cursor::new(buf.into()), |e| {
|
||||
assert_eq!(e, input.remove(0).reify().unwrap());
|
||||
}).unwrap();
|
||||
|
||||
assert_eq!(0, input.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Case {
|
||||
seqno: u64,
|
||||
wire: Vec<u8>,
|
||||
expect: Vec<(String, String)>,
|
||||
header_table_size: Option<usize>,
|
||||
}
|
||||
|
||||
fn key_str(e: &Header) -> &str {
|
||||
match *e {
|
||||
Header::Field { ref name, .. } => name.as_str(),
|
||||
Header::Authority(..) => ":authority",
|
||||
Header::Method(..) => ":method",
|
||||
Header::Scheme(..) => ":scheme",
|
||||
Header::Path(..) => ":path",
|
||||
Header::Status(..) => ":status",
|
||||
}
|
||||
}
|
||||
|
||||
fn value_str(e: &Header) -> &str {
|
||||
match *e {
|
||||
Header::Field { ref value, .. } => value.to_str().unwrap(),
|
||||
Header::Authority(ref v) => &**v,
|
||||
Header::Method(ref m) => m.as_str(),
|
||||
Header::Scheme(ref v) => &**v,
|
||||
Header::Path(ref v) => &**v,
|
||||
Header::Status(ref v) => v.as_str(),
|
||||
}
|
||||
}
|
||||
2
src/hpack/test/mod.rs
Normal file
2
src/hpack/test/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
mod fixture;
|
||||
mod fuzz;
|
||||
7
util/genfixture/Cargo.toml
Normal file
7
util/genfixture/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "genfixture"
|
||||
version = "0.1.0"
|
||||
authors = ["Carl Lerche <me@carllerche.com>"]
|
||||
|
||||
[dependencies]
|
||||
walkdir = "1.0.0"
|
||||
64
util/genfixture/src/main.rs
Normal file
64
util/genfixture/src/main.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
extern crate walkdir;
|
||||
|
||||
use self::walkdir::WalkDir;
|
||||
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<_> = env::args().collect();
|
||||
|
||||
let path = args.get(1).expect("usage: genfixture [PATH]");
|
||||
let path = Path::new(path);
|
||||
|
||||
let mut tests = HashMap::new();
|
||||
|
||||
for entry in WalkDir::new(path) {
|
||||
let entry = entry.unwrap();
|
||||
let path = entry.path().to_str().unwrap();
|
||||
|
||||
if !path.ends_with(".json") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if path.contains("raw-data") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the relevant part
|
||||
let fixture_path = path.split("fixtures/hpack/").last().unwrap();
|
||||
|
||||
// Now, split that into the group and the name
|
||||
let module = fixture_path.split("/").next().unwrap();
|
||||
|
||||
tests.entry(module.to_string()).or_insert(vec![])
|
||||
.push(fixture_path.to_string());
|
||||
}
|
||||
|
||||
let mut one = false;
|
||||
|
||||
for (module, tests) in tests {
|
||||
let module = module.replace("-", "_");
|
||||
|
||||
if one {
|
||||
println!("");
|
||||
}
|
||||
|
||||
one = true;
|
||||
|
||||
println!("fixture_mod!(");
|
||||
println!(" {} => {{", module);
|
||||
|
||||
for test in tests {
|
||||
let ident = test
|
||||
.split("/").nth(1).unwrap()
|
||||
.split(".").next().unwrap();
|
||||
|
||||
println!(" ({}, {:?});", ident, test);
|
||||
}
|
||||
|
||||
println!(" }}");
|
||||
println!(");");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user