summaryrefslogtreecommitdiffstats
path: root/third_party/rust/h2/src/hpack/test
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/h2/src/hpack/test')
-rw-r--r--third_party/rust/h2/src/hpack/test/fixture.rs615
-rw-r--r--third_party/rust/h2/src/hpack/test/fuzz.rs365
-rw-r--r--third_party/rust/h2/src/hpack/test/mod.rs2
3 files changed, 982 insertions, 0 deletions
diff --git a/third_party/rust/h2/src/hpack/test/fixture.rs b/third_party/rust/h2/src/hpack/test/fixture.rs
new file mode 100644
index 0000000000..d3f76e3bf8
--- /dev/null
+++ b/third_party/rust/h2/src/hpack/test/fixture.rs
@@ -0,0 +1,615 @@
+use crate::hpack::{Decoder, Encoder, Header};
+
+use bytes::BytesMut;
+use hex::FromHex;
+use 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,
+ 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);
+ }
+
+ let mut buf = BytesMut::with_capacity(case.wire.len());
+ buf.extend_from_slice(&case.wire);
+ decoder
+ .decode(&mut Cursor::new(&mut buf), |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 limit = 64 * 1024;
+ let mut buf = BytesMut::with_capacity(limit);
+
+ 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(|(name, value)| {
+ Header::new(name.clone().into(), value.clone().into())
+ .unwrap()
+ .into()
+ })
+ .collect();
+
+ encoder.encode(&mut input.clone().into_iter(), &mut buf);
+
+ decoder
+ .decode(&mut Cursor::new(&mut buf), |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::Protocol(..) => ":protocol",
+ 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::Protocol(ref v) => v.as_str(),
+ 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");
+ }
+);
diff --git a/third_party/rust/h2/src/hpack/test/fuzz.rs b/third_party/rust/h2/src/hpack/test/fuzz.rs
new file mode 100644
index 0000000000..af9e8ea23a
--- /dev/null
+++ b/third_party/rust/h2/src/hpack/test/fuzz.rs
@@ -0,0 +1,365 @@
+use crate::hpack::{Decoder, Encoder, Header};
+
+use http::header::{HeaderName, HeaderValue};
+
+use bytes::BytesMut;
+use quickcheck::{Arbitrary, Gen, QuickCheck, TestResult};
+use rand::distributions::Slice;
+use rand::rngs::StdRng;
+use rand::{thread_rng, Rng, SeedableRng};
+
+use std::io::Cursor;
+
+const MAX_CHUNK: usize = 2 * 1024;
+
+#[test]
+fn hpack_fuzz() {
+ let _ = env_logger::try_init();
+ fn prop(fuzz: FuzzHpack) -> TestResult {
+ fuzz.run();
+ TestResult::from_bool(true)
+ }
+
+ QuickCheck::new()
+ .tests(100)
+ .quickcheck(prop as fn(FuzzHpack) -> TestResult)
+}
+
+/*
+// If wanting to test with a specific feed, uncomment and fill in the seed.
+#[test]
+fn hpack_fuzz_seeded() {
+ let _ = env_logger::try_init();
+ let seed = [/* fill me in*/];
+ FuzzHpack::new(seed).run();
+}
+*/
+
+#[derive(Debug, Clone)]
+struct FuzzHpack {
+ // The set of headers to encode / decode
+ frames: Vec<HeaderFrame>,
+}
+
+#[derive(Debug, Clone)]
+struct HeaderFrame {
+ resizes: Vec<usize>,
+ headers: Vec<Header<Option<HeaderName>>>,
+}
+
+impl FuzzHpack {
+ fn new(seed: [u8; 32]) -> FuzzHpack {
+ // Seed the RNG
+ let mut rng = StdRng::from_seed(seed);
+
+ // Generates a bunch of source headers
+ let mut source: Vec<Header<Option<HeaderName>>> = vec![];
+
+ for _ in 0..2000 {
+ source.push(gen_header(&mut rng));
+ }
+
+ // Actual test run headers
+ let num: usize = rng.gen_range(40..500);
+
+ let mut frames: Vec<HeaderFrame> = vec![];
+ let mut added = 0;
+
+ let skew: i32 = rng.gen_range(1..5);
+
+ // Rough number of headers to add
+ while added < num {
+ let mut frame = HeaderFrame {
+ resizes: vec![],
+ headers: vec![],
+ };
+
+ match rng.gen_range(0..20) {
+ 0 => {
+ // Two resizes
+ let high = rng.gen_range(128..MAX_CHUNK * 2);
+ let low = rng.gen_range(0..high);
+
+ frame.resizes.extend([low, high]);
+ }
+ 1..=3 => {
+ frame.resizes.push(rng.gen_range(128..MAX_CHUNK * 2));
+ }
+ _ => {}
+ }
+
+ let mut is_name_required = true;
+
+ for _ in 0..rng.gen_range(1..(num - added) + 1) {
+ let x: f64 = rng.gen_range(0.0..1.0);
+ let x = x.powi(skew);
+
+ let i = (x * source.len() as f64) as usize;
+
+ let header = &source[i];
+ match header {
+ Header::Field { name: None, .. } => {
+ if is_name_required {
+ continue;
+ }
+ }
+ Header::Field { .. } => {
+ is_name_required = false;
+ }
+ _ => {
+ // pseudos can't be followed by a header with no name
+ is_name_required = true;
+ }
+ }
+
+ frame.headers.push(header.clone());
+
+ added += 1;
+ }
+
+ frames.push(frame);
+ }
+
+ FuzzHpack { frames }
+ }
+
+ fn run(self) {
+ let frames = self.frames;
+ let mut expect = vec![];
+
+ let mut encoder = Encoder::default();
+ let mut decoder = Decoder::default();
+
+ for frame in frames {
+ // build "expected" frames, such that decoding headers always
+ // includes a name
+ let mut prev_name = None;
+ for header in &frame.headers {
+ match header.clone().reify() {
+ Ok(h) => {
+ prev_name = match h {
+ Header::Field { ref name, .. } => Some(name.clone()),
+ _ => None,
+ };
+ expect.push(h);
+ }
+ Err(value) => {
+ expect.push(Header::Field {
+ name: prev_name.as_ref().cloned().expect("previous header name"),
+ value,
+ });
+ }
+ }
+ }
+
+ let mut buf = BytesMut::new();
+
+ if let Some(max) = frame.resizes.iter().max() {
+ decoder.queue_size_update(*max);
+ }
+
+ // Apply resizes
+ for resize in &frame.resizes {
+ encoder.update_max_size(*resize);
+ }
+
+ encoder.encode(frame.headers, &mut buf);
+
+ // Decode the chunk!
+ decoder
+ .decode(&mut Cursor::new(&mut buf), |h| {
+ let e = expect.remove(0);
+ assert_eq!(h, e);
+ })
+ .expect("full decode");
+ }
+
+ assert_eq!(0, expect.len());
+ }
+}
+
+impl Arbitrary for FuzzHpack {
+ fn arbitrary(_: &mut Gen) -> Self {
+ FuzzHpack::new(thread_rng().gen())
+ }
+}
+
+fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> {
+ use http::{Method, StatusCode};
+
+ if g.gen_ratio(1, 10) {
+ match g.gen_range(0u32..5) {
+ 0 => {
+ let value = gen_string(g, 4, 20);
+ Header::Authority(to_shared(value))
+ }
+ 1 => {
+ let method = match g.gen_range(0u32..6) {
+ 0 => Method::GET,
+ 1 => Method::POST,
+ 2 => Method::PUT,
+ 3 => Method::PATCH,
+ 4 => Method::DELETE,
+ 5 => {
+ let n: usize = g.gen_range(3..7);
+ let bytes: Vec<u8> = (0..n)
+ .map(|_| *g.sample(Slice::new(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ").unwrap()))
+ .collect();
+
+ Method::from_bytes(&bytes).unwrap()
+ }
+ _ => unreachable!(),
+ };
+
+ Header::Method(method)
+ }
+ 2 => {
+ let value = match g.gen_range(0u32..2) {
+ 0 => "http",
+ 1 => "https",
+ _ => unreachable!(),
+ };
+
+ Header::Scheme(to_shared(value.to_string()))
+ }
+ 3 => {
+ let value = match g.gen_range(0u32..100) {
+ 0 => "/".to_string(),
+ 1 => "/index.html".to_string(),
+ _ => gen_string(g, 2, 20),
+ };
+
+ Header::Path(to_shared(value))
+ }
+ 4 => {
+ let status = (g.gen::<u16>() % 500) + 100;
+
+ Header::Status(StatusCode::from_u16(status).unwrap())
+ }
+ _ => unreachable!(),
+ }
+ } else {
+ let name = if g.gen_ratio(1, 10) {
+ None
+ } else {
+ Some(gen_header_name(g))
+ };
+ let mut value = gen_header_value(g);
+
+ if g.gen_ratio(1, 30) {
+ value.set_sensitive(true);
+ }
+
+ Header::Field { name, value }
+ }
+}
+
+fn gen_header_name(g: &mut StdRng) -> HeaderName {
+ use http::header;
+
+ if g.gen_ratio(1, 2) {
+ g.sample(
+ Slice::new(&[
+ header::ACCEPT,
+ header::ACCEPT_CHARSET,
+ header::ACCEPT_ENCODING,
+ header::ACCEPT_LANGUAGE,
+ header::ACCEPT_RANGES,
+ header::ACCESS_CONTROL_ALLOW_CREDENTIALS,
+ header::ACCESS_CONTROL_ALLOW_HEADERS,
+ header::ACCESS_CONTROL_ALLOW_METHODS,
+ header::ACCESS_CONTROL_ALLOW_ORIGIN,
+ header::ACCESS_CONTROL_EXPOSE_HEADERS,
+ header::ACCESS_CONTROL_MAX_AGE,
+ header::ACCESS_CONTROL_REQUEST_HEADERS,
+ header::ACCESS_CONTROL_REQUEST_METHOD,
+ header::AGE,
+ header::ALLOW,
+ header::ALT_SVC,
+ header::AUTHORIZATION,
+ header::CACHE_CONTROL,
+ header::CONNECTION,
+ header::CONTENT_DISPOSITION,
+ header::CONTENT_ENCODING,
+ header::CONTENT_LANGUAGE,
+ header::CONTENT_LENGTH,
+ header::CONTENT_LOCATION,
+ header::CONTENT_RANGE,
+ header::CONTENT_SECURITY_POLICY,
+ header::CONTENT_SECURITY_POLICY_REPORT_ONLY,
+ header::CONTENT_TYPE,
+ header::COOKIE,
+ header::DNT,
+ header::DATE,
+ header::ETAG,
+ header::EXPECT,
+ header::EXPIRES,
+ header::FORWARDED,
+ header::FROM,
+ header::HOST,
+ header::IF_MATCH,
+ header::IF_MODIFIED_SINCE,
+ header::IF_NONE_MATCH,
+ header::IF_RANGE,
+ header::IF_UNMODIFIED_SINCE,
+ header::LAST_MODIFIED,
+ header::LINK,
+ header::LOCATION,
+ header::MAX_FORWARDS,
+ header::ORIGIN,
+ header::PRAGMA,
+ header::PROXY_AUTHENTICATE,
+ header::PROXY_AUTHORIZATION,
+ header::PUBLIC_KEY_PINS,
+ header::PUBLIC_KEY_PINS_REPORT_ONLY,
+ header::RANGE,
+ header::REFERER,
+ header::REFERRER_POLICY,
+ header::REFRESH,
+ header::RETRY_AFTER,
+ header::SERVER,
+ header::SET_COOKIE,
+ header::STRICT_TRANSPORT_SECURITY,
+ header::TE,
+ header::TRAILER,
+ header::TRANSFER_ENCODING,
+ header::USER_AGENT,
+ header::UPGRADE,
+ header::UPGRADE_INSECURE_REQUESTS,
+ header::VARY,
+ header::VIA,
+ header::WARNING,
+ header::WWW_AUTHENTICATE,
+ header::X_CONTENT_TYPE_OPTIONS,
+ header::X_DNS_PREFETCH_CONTROL,
+ header::X_FRAME_OPTIONS,
+ header::X_XSS_PROTECTION,
+ ])
+ .unwrap(),
+ )
+ .clone()
+ } else {
+ let value = gen_string(g, 1, 25);
+ HeaderName::from_bytes(value.as_bytes()).unwrap()
+ }
+}
+
+fn gen_header_value(g: &mut StdRng) -> HeaderValue {
+ let value = gen_string(g, 0, 70);
+ HeaderValue::from_bytes(value.as_bytes()).unwrap()
+}
+
+fn gen_string(g: &mut StdRng, min: usize, max: usize) -> String {
+ let bytes: Vec<_> = (min..max)
+ .map(|_| {
+ // Chars to pick from
+ *g.sample(Slice::new(b"ABCDEFGHIJKLMNOPQRSTUVabcdefghilpqrstuvwxyz----").unwrap())
+ })
+ .collect();
+
+ String::from_utf8(bytes).unwrap()
+}
+
+fn to_shared(src: String) -> crate::hpack::BytesStr {
+ crate::hpack::BytesStr::from(src.as_str())
+}
diff --git a/third_party/rust/h2/src/hpack/test/mod.rs b/third_party/rust/h2/src/hpack/test/mod.rs
new file mode 100644
index 0000000000..9b1f27169d
--- /dev/null
+++ b/third_party/rust/h2/src/hpack/test/mod.rs
@@ -0,0 +1,2 @@
+mod fixture;
+mod fuzz;