diff --git a/src/header/common/accept.rs b/src/header/common/accept.rs index 02522deaf0..c991cab422 100644 --- a/src/header/common/accept.rs +++ b/src/header/common/accept.rs @@ -27,32 +27,39 @@ header! { #[doc="* Using always Mime types to represent `media-range` differs from the ABNF."] #[doc="* **FIXME**: `accept-ext` is not supported."] (Accept, "Accept") => (QualityItem)+ -} - -#[cfg(test)] -mod tests { - use mime::*; - - use header::{Header, Quality, QualityItem, qitem}; - - use super::Accept; - - #[test] - fn test_parse_header_no_quality() { - let a: Accept = Header::parse_header([b"text/plain; charset=utf-8".to_vec()].as_ref()).unwrap(); - let b = Accept(vec![ - qitem(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])), - ]); - assert_eq!(a, b); - } - #[test] - fn test_parse_header_with_quality() { - let a: Accept = Header::parse_header([b"text/plain; charset=utf-8; q=0.5".to_vec()].as_ref()).unwrap(); - let b = Accept(vec![ - QualityItem::new(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]), Quality(500)), - ]); - assert_eq!(a, b); + test_accept { + // Tests from the RFC + // FIXME: Test fails, first value containing a "*" fails to parse + // test_header!( + // test1, + // vec![b"audio/*; q=0.2, audio/basic"], + // Some(HeaderField(vec![ + // QualityItem::new(Mime(TopLevel::Audio, SubLevel::Star, vec![]), Quality(200)), + // qitem(Mime(TopLevel::Audio, SubLevel::Ext("basic".to_string()), vec![])), + // ]))); + test_header!( + test2, + vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"], + Some(HeaderField(vec![ + QualityItem::new(Mime(TopLevel::Text, SubLevel::Plain, vec![]), Quality(500)), + qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])), + QualityItem::new(Mime(TopLevel::Text, SubLevel::Ext("x-dvi".to_string()), vec![]), Quality(800)), + qitem(Mime(TopLevel::Text, SubLevel::Ext("x-c".to_string()), vec![])), + ]))); + // Custom tests + test_header!( + test3, + vec![b"text/plain; charset=utf-8"], + Some(Accept(vec![ + qitem(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])), + ]))); + test_header!( + test4, + vec![b"text/plain; charset=utf-8; q=0.5"], + Some(Accept(vec![ + QualityItem::new(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]), Quality(500)), + ]))); } } diff --git a/src/header/common/accept_charset.rs b/src/header/common/accept_charset.rs index 7b36bd9d18..53ae264c05 100644 --- a/src/header/common/accept_charset.rs +++ b/src/header/common/accept_charset.rs @@ -16,6 +16,10 @@ header! { #[doc="Accept-Charset = 1#( ( charset / \"*\" ) [ weight ] )"] #[doc="```"] (AcceptCharset, "Accept-Charset") => (QualityItem)+ + + test_accept_charset { + test_header!(test1, vec![b"iso-8859-5, unicode-1-1;q=0.8"]); + } } diff --git a/src/header/common/accept_language.rs b/src/header/common/accept_language.rs index 3cc95c52ba..ef478c4c97 100644 --- a/src/header/common/accept_language.rs +++ b/src/header/common/accept_language.rs @@ -49,6 +49,10 @@ header! { #[doc="language-range = "] #[doc="```"] (AcceptLanguage, "Accept-Language") => (QualityItem)+ + + test_accept_language { + test_header!(test1, vec![b"da, en-gb;q=0.8, en;q=0.7"]); + } } #[cfg(test)] diff --git a/src/header/common/content_encoding.rs b/src/header/common/content_encoding.rs index beab9654c5..d457012570 100644 --- a/src/header/common/content_encoding.rs +++ b/src/header/common/content_encoding.rs @@ -17,6 +17,8 @@ header! { #[doc="Content-Encoding = 1#content-coding"] #[doc="```"] (ContentEncoding, "Content-Encoding") => (Encoding)+ + + test_content_encoding {} } bench_header!(single, ContentEncoding, { vec![b"gzip".to_vec()] }); diff --git a/src/header/common/mod.rs b/src/header/common/mod.rs index 8168d9656c..68ff14c8eb 100644 --- a/src/header/common/mod.rs +++ b/src/header/common/mod.rs @@ -94,6 +94,29 @@ macro_rules! deref( } ); +macro_rules! test_header { + ($id:ident, $test:expr) => { + #[test] + fn $id() { + let a: Vec> = $test.iter().map(|x| x.to_vec()).collect(); + HeaderField::parse_header(&a[..]).unwrap(); + } + }; + ($id:ident, $raw:expr, $typed:expr) => { + #[test] + fn $id() { + use std::str; + let a: Vec> = $raw.iter().map(|x| x.to_vec()).collect(); + let val = HeaderField::parse_header(&a[..]); + // Test parsing + assert_eq!(val, $typed); + // Test formatting + let res: &str = str::from_utf8($raw[0]).unwrap(); + assert_eq!(format!("{}", $typed.unwrap()), res); + } + } +} + #[macro_export] macro_rules! header { // $a:meta: Attributes associated with the header item (usually docs) @@ -129,7 +152,7 @@ macro_rules! header { }; // List header, one or more items - ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)+) => { + ($(#[$a:meta])*($id:ident, $n:expr) => ($item:ty)+ $tm:ident{$($tf:item)*}) => { $(#[$a])* #[derive(Clone, Debug, PartialEq)] pub struct $id(pub Vec<$item>); @@ -153,6 +176,14 @@ macro_rules! header { self.fmt_header(f) } } + + #[allow(unused_imports)] + mod $tm{ + use $crate::header::*; + use $crate::mime::*; + use super::$id as HeaderField; + $($tf)* + } }; // Single value header ($(#[$a:meta])*($id:ident, $n:expr) => [$value:ty]) => { diff --git a/src/header/common/transfer_encoding.rs b/src/header/common/transfer_encoding.rs index 4e8db0e95d..18ea3f26e3 100644 --- a/src/header/common/transfer_encoding.rs +++ b/src/header/common/transfer_encoding.rs @@ -14,6 +14,16 @@ header! { #[doc="Transfer-Encoding = 1#transfer-coding"] #[doc="```"] (TransferEncoding, "Transfer-Encoding") => (Encoding)+ + + transfer_encoding { + test_header!( + test1, + vec![b"gzip, chunked"], + Some(HeaderField( + vec![Encoding::Gzip, Encoding::Chunked] + ))); + + } } bench_header!(normal, TransferEncoding, { vec![b"chunked, gzip".to_vec()] }); diff --git a/src/header/common/upgrade.rs b/src/header/common/upgrade.rs index b807199475..b47d2c2ea6 100644 --- a/src/header/common/upgrade.rs +++ b/src/header/common/upgrade.rs @@ -26,6 +26,18 @@ header! { #[doc="protocol-version = token"] #[doc="```"] (Upgrade, "Upgrade") => (Protocol)+ + + test_upgrade { + test_header!( + test1, + vec![b"HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11"], + Some(HeaderField(vec![ + Protocol::ProtocolExt("HTTP/2.0".to_string()), + Protocol::ProtocolExt("SHTTP/1.3".to_string()), + Protocol::ProtocolExt("IRC/6.9".to_string()), + Protocol::ProtocolExt("RTA/x11".to_string()), + ]))); + } } /// Protocol values that can appear in the Upgrade header.