Skip to content

Commit

Permalink
test(headers): Allow tests inside list header macros, add tests.
Browse files Browse the repository at this point in the history
Adds test cases from the relevant RFCs for a few headers.
See also: #468, do we want the test cases rendered as examples in the docs?
  • Loading branch information
pyfisch committed Apr 26, 2015
1 parent 9d83ed6 commit efd6c96
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 26 deletions.
57 changes: 32 additions & 25 deletions src/header/common/accept.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Mime>)+
}

#[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)),
])));
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/header/common/accept_charset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ header! {
#[doc="Accept-Charset = 1#( ( charset / \"*\" ) [ weight ] )"]
#[doc="```"]
(AcceptCharset, "Accept-Charset") => (QualityItem<Charset>)+

test_accept_charset {
test_header!(test1, vec![b"iso-8859-5, unicode-1-1;q=0.8"]);
}
}


Expand Down
4 changes: 4 additions & 0 deletions src/header/common/accept_language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ header! {
#[doc="language-range = <language-range, see [RFC4647], Section 2.1>"]
#[doc="```"]
(AcceptLanguage, "Accept-Language") => (QualityItem<Language>)+

test_accept_language {
test_header!(test1, vec![b"da, en-gb;q=0.8, en;q=0.7"]);
}
}

#[cfg(test)]
Expand Down
2 changes: 2 additions & 0 deletions src/header/common/content_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()] });
Expand Down
33 changes: 32 additions & 1 deletion src/header/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,29 @@ macro_rules! deref(
}
);

macro_rules! test_header {
($id:ident, $test:expr) => {
#[test]
fn $id() {
let a: Vec<Vec<u8>> = $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<Vec<u8>> = $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)
Expand Down Expand Up @@ -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>);
Expand All @@ -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]) => {
Expand Down
10 changes: 10 additions & 0 deletions src/header/common/transfer_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()] });
Expand Down
12 changes: 12 additions & 0 deletions src/header/common/upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit efd6c96

Please sign in to comment.