From ff346f147f010d55aa7198ccf2f59f299ee3a983 Mon Sep 17 00:00:00 2001 From: Pyfisch Date: Fri, 1 May 2015 14:31:53 +0200 Subject: [PATCH] refactor(hyper): add tests and refactor to increase coverage --- src/header/common/accept_ranges.rs | 3 ++ src/header/common/connection.rs | 74 ++++++++++++------------------ src/header/common/if_range.rs | 4 +- src/header/common/mod.rs | 2 - src/header/shared/entity.rs | 9 +--- src/header/shared/httpdate.rs | 5 ++ src/method.rs | 6 +++ 7 files changed, 49 insertions(+), 54 deletions(-) diff --git a/src/header/common/accept_ranges.rs b/src/header/common/accept_ranges.rs index 568f4b47..5c620f80 100644 --- a/src/header/common/accept_ranges.rs +++ b/src/header/common/accept_ranges.rs @@ -16,12 +16,15 @@ header! { #[doc="# Example values"] #[doc="* `bytes`"] #[doc="* `none`"] + #[doc="* `unknown-unit`"] #[doc="```"] (AcceptRanges, "Accept-Ranges") => (RangeUnit)+ test_acccept_ranges { test_header!(test1, vec![b"bytes"]); test_header!(test2, vec![b"none"]); + test_header!(test3, vec![b"unknown-unit"]); + test_header!(test4, vec![b"bytes, unknown-unit"]); } } diff --git a/src/header/common/connection.rs b/src/header/common/connection.rs index 32f8d727..c4ad673d 100644 --- a/src/header/common/connection.rs +++ b/src/header/common/connection.rs @@ -1,34 +1,9 @@ -use header::{Header, HeaderFormat}; use std::fmt::{self, Display}; use std::str::FromStr; -use header::parsing::{from_comma_delimited, fmt_comma_delimited}; use unicase::UniCase; pub use self::ConnectionOption::{KeepAlive, Close, ConnectionHeader}; -/// `Connection` header, defined in [RFC7230](https://tools.ietf.org/html/rfc7230#section-6.1) -/// -/// The `Connection` header field allows the sender to indicate desired -/// control options for the current connection. In order to avoid -/// confusing downstream recipients, a proxy or gateway MUST remove or -/// replace any received connection options before forwarding the -/// message. -/// -/// # ABNF -/// ```plain -/// Connection = 1#connection-option -/// connection-option = token -/// ``` -/// -/// # Example values -/// * `close` -/// * `upgrade` -/// * `keep-alive` -#[derive(Clone, PartialEq, Debug)] -pub struct Connection(pub Vec); - -deref!(Connection => Vec); - /// Values that can be in the `Connection` header. #[derive(Clone, PartialEq, Debug)] pub enum ConnectionOption { @@ -50,11 +25,11 @@ pub enum ConnectionOption { impl FromStr for ConnectionOption { type Err = (); fn from_str(s: &str) -> Result { - Ok(match s { - "keep-alive" => KeepAlive, - "close" => Close, - s => ConnectionHeader(UniCase(s.to_string())), - }) + match s { + "keep-alive" => Ok(KeepAlive), + "close" => Ok(Close), + s => Ok(ConnectionHeader(UniCase(s.to_string()))) + } } } @@ -63,25 +38,36 @@ impl Display for ConnectionOption { f.write_str(match *self { KeepAlive => "keep-alive", Close => "close", - ConnectionHeader(UniCase(ref s)) => s, + ConnectionHeader(UniCase(ref s)) => s.as_ref() }) } } -impl Header for Connection { - fn header_name() -> &'static str { - "Connection" - } +header! { + #[doc="`Connection` header, defined in"] + #[doc="[RFC7230](http://tools.ietf.org/html/rfc7230#section-6.1)"] + #[doc=""] + #[doc="The `Connection` header field allows the sender to indicate desired"] + #[doc="control options for the current connection. In order to avoid"] + #[doc="confusing downstream recipients, a proxy or gateway MUST remove or"] + #[doc="replace any received connection options before forwarding the"] + #[doc="message."] + #[doc=""] + #[doc="# ABNF"] + #[doc="```plain"] + #[doc="Connection = 1#connection-option"] + #[doc="connection-option = token"] + #[doc=""] + #[doc="# Example values"] + #[doc="* `close`"] + #[doc="* `keep-alive`"] + #[doc="* `upgrade`"] + (Connection, "Connection") => (ConnectionOption)+ - fn parse_header(raw: &[Vec]) -> Option { - from_comma_delimited(raw).map(|vec| Connection(vec)) - } -} - -impl HeaderFormat for Connection { - fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Connection(ref parts) = *self; - fmt_comma_delimited(f, &parts[..]) + test_connection { + test_header!(test1, vec![b"close"]); + test_header!(test2, vec![b"keep-alive"]); + test_header!(test3, vec![b"upgrade"]); } } diff --git a/src/header/common/if_range.rs b/src/header/common/if_range.rs index 4454c0c6..c3b0f120 100644 --- a/src/header/common/if_range.rs +++ b/src/header/common/if_range.rs @@ -65,9 +65,11 @@ impl Display for IfRange { } #[cfg(test)] -mod test_range { +mod test_if_range { + use std::str; use header::*; use super::IfRange as HeaderField; test_header!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]); test_header!(test2, vec![b"\"xyzzy\""]); + test_header!(test3, vec![b"this-is-invalid"], None::); } diff --git a/src/header/common/mod.rs b/src/header/common/mod.rs index 3702cd29..553ba783 100644 --- a/src/header/common/mod.rs +++ b/src/header/common/mod.rs @@ -256,8 +256,6 @@ macro_rules! header { if raw.len() == 1 { if raw[0] == b"*" { return Some($id::Any) - } else if raw[0] == b"" { - return None } } $crate::header::parsing::from_comma_delimited(raw).map(|vec| $id::Items(vec)) diff --git a/src/header/shared/entity.rs b/src/header/shared/entity.rs index ec722186..891d6c9f 100644 --- a/src/header/shared/entity.rs +++ b/src/header/shared/entity.rs @@ -6,13 +6,8 @@ use std::fmt::{self, Display}; // 2. in the range %x23 to %x7E, or // 3. in the range %x80 to %xFF fn check_slice_validity(slice: &str) -> bool { - for c in slice.bytes() { - match c { - b'\x21' | b'\x23' ... b'\x7e' | b'\x80' ... b'\xff' => (), - _ => { return false; } - } - } - true + slice.bytes().all(|c| + c == b'\x21' || (c >= b'\x23' && c <= b'\x7e') | (c >= b'\x80' && c <= b'\xff')) } /// An entity tag, defined in [RFC7232](https://tools.ietf.org/html/rfc7232#section-2.3) diff --git a/src/header/shared/httpdate.rs b/src/header/shared/httpdate.rs index f89b56db..79de11c2 100644 --- a/src/header/shared/httpdate.rs +++ b/src/header/shared/httpdate.rs @@ -83,4 +83,9 @@ mod tests { fn test_asctime() { assert_eq!("Sun Nov 7 08:48:37 1994".parse(), Ok(NOV_07)); } + + #[test] + fn test_no_date() { + assert_eq!("this-is-no-date".parse(), Err::(())); + } } diff --git a/src/method.rs b/src/method.rs index f3f37aab..8cfedb4f 100644 --- a/src/method.rs +++ b/src/method.rs @@ -129,6 +129,7 @@ impl fmt::Display for Method { mod tests { use std::collections::HashMap; use std::str::FromStr; + use error::Error; use super::Method; use super::Method::{Get, Post, Put, Extension}; @@ -150,6 +151,11 @@ mod tests { assert_eq!(Get, FromStr::from_str("GET").unwrap()); assert_eq!(Extension("MOVE".to_string()), FromStr::from_str("MOVE").unwrap()); + let x: Result = FromStr::from_str(""); + if let Err(Error::Method) = x { + } else { + panic!("An empty method is invalid!") + } } #[test]