Add HPACK test cases
This commit is contained in:
@@ -2,9 +2,10 @@ mod encoder;
|
||||
mod decoder;
|
||||
mod entry;
|
||||
mod huffman;
|
||||
// mod table;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
pub use self::encoder::Encoder;
|
||||
pub use self::entry::{Entry, Key};
|
||||
pub use self::decoder::{Decoder, DecoderError};
|
||||
// pub use self::table::Entry;
|
||||
|
||||
134
src/hpack/test.rs
Normal file
134
src/hpack/test.rs
Normal file
@@ -0,0 +1,134 @@
|
||||
extern crate hex;
|
||||
extern crate walkdir;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
|
||||
use super::{Entry, Decoder};
|
||||
|
||||
use self::hex::FromHex;
|
||||
use self::serde_json::Value;
|
||||
use self::walkdir::WalkDir;
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
#[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;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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(&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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Case {
|
||||
seqno: u64,
|
||||
wire: Vec<u8>,
|
||||
expect: Vec<(String, String)>,
|
||||
header_table_size: Option<usize>,
|
||||
}
|
||||
|
||||
fn key_str(e: &Entry) -> &str {
|
||||
match *e {
|
||||
Entry::Header { ref name, .. } => name.as_str(),
|
||||
Entry::Authority(..) => ":authority",
|
||||
Entry::Method(..) => ":method",
|
||||
Entry::Scheme(..) => ":scheme",
|
||||
Entry::Path(..) => ":path",
|
||||
Entry::Status(..) => ":status",
|
||||
}
|
||||
}
|
||||
|
||||
fn value_str(e: &Entry) -> &str {
|
||||
match *e {
|
||||
Entry::Header { ref value, .. } => value.to_str().unwrap(),
|
||||
Entry::Authority(ref v) => &**v,
|
||||
Entry::Method(ref m) => m.as_str(),
|
||||
Entry::Scheme(ref v) => &**v,
|
||||
Entry::Path(ref v) => &**v,
|
||||
Entry::Status(ref v) => v.as_str(),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user