Merge pull request #204 from amousset/improve-response-parsing

feat(transport-smtp): Add tests for response parsing and clean from_str
This commit is contained in:
Alexis Mousset
2017-11-19 01:44:26 +01:00
committed by GitHub
2 changed files with 101 additions and 201 deletions

View File

@@ -313,9 +313,7 @@ mod test {
use super::*; use super::*;
use smtp::extension::MailBodyParameter; use smtp::extension::MailBodyParameter;
#[cfg(feature = "crammd5-auth")] #[cfg(feature = "crammd5-auth")]
use smtp::response::Code; use smtp::response::{Category, Code, Detail, Severity};
#[cfg(feature = "crammd5-auth")]
use std::str::FromStr;
#[test] #[test]
fn test_display() { fn test_display() {
@@ -418,7 +416,14 @@ mod test {
AuthCommand::new_from_response( AuthCommand::new_from_response(
Mechanism::CramMd5, Mechanism::CramMd5,
credentials.clone(), credentials.clone(),
&Response::new(Code::from_str("334").unwrap(), vec!["dGVzdAo=".to_string()]), &Response::new(
Code::new(
Severity::PositiveIntermediate,
Category::Unspecified3,
Detail(4),
),
vec!["dGVzdAo=".to_string()],
),
).unwrap() ).unwrap()
), ),
"dXNlciA1NTIzNThiMzExOWFjOWNkYzM2YWRiN2MxNWRmMWJkNw==\r\n" "dXNlciA1NTIzNThiMzExOWFjOWNkYzM2YWRiN2MxNWRmMWJkNw==\r\n"

View File

@@ -23,18 +23,6 @@ pub enum Severity {
PermanentNegativeCompletion = 5, PermanentNegativeCompletion = 5,
} }
impl FromStr for Severity {
type Err = NomError;
fn from_str(s: &str) -> result::Result<Severity, NomError> {
match parse_severity(s.as_bytes()) {
NomResult::Done(_, res) => Ok(res),
NomResult::Error(e) => Err(e),
NomResult::Incomplete(_) => Err(NomErrorKind::Complete),
}
}
}
impl Display for Severity { impl Display for Severity {
fn fmt(&self, f: &mut Formatter) -> Result { fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{}", *self as u8) write!(f, "{}", *self as u8)
@@ -58,18 +46,6 @@ pub enum Category {
MailSystem = 5, MailSystem = 5,
} }
impl FromStr for Category {
type Err = NomError;
fn from_str(s: &str) -> result::Result<Category, NomError> {
match parse_category(s.as_bytes()) {
NomResult::Done(_, res) => Ok(res),
NomResult::Error(e) => Err(e),
NomResult::Incomplete(_) => Err(NomErrorKind::Complete),
}
}
}
impl Display for Category { impl Display for Category {
fn fmt(&self, f: &mut Formatter) -> Result { fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{}", *self as u8) write!(f, "{}", *self as u8)
@@ -80,19 +56,6 @@ impl Display for Category {
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub struct Detail(pub u8); pub struct Detail(pub u8);
impl FromStr for Detail {
type Err = NomError;
fn from_str(s: &str) -> result::Result<Detail, NomError> {
match parse_detail(s.as_bytes()) {
NomResult::Done(_, res) => Ok(res),
NomResult::Error(e) => Err(e),
NomResult::Incomplete(_) => Err(NomErrorKind::Complete),
}
}
}
impl Display for Detail { impl Display for Detail {
fn fmt(&self, f: &mut Formatter) -> Result { fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{}", self.0) write!(f, "{}", self.0)
@@ -116,18 +79,6 @@ impl Display for Code {
} }
} }
impl FromStr for Code {
type Err = NomError;
fn from_str(s: &str) -> result::Result<Code, NomError> {
match parse_code(s.as_bytes()) {
NomResult::Done(_, res) => Ok(res),
NomResult::Error(e) => Err(e),
NomResult::Incomplete(_) => Err(NomErrorKind::Complete),
}
}
}
impl Code { impl Code {
/// Creates a new `Code` structure /// Creates a new `Code` structure
pub fn new(severity: Severity, category: Category, detail: Detail) -> Code { pub fn new(severity: Severity, category: Category, detail: Detail) -> Code {
@@ -217,8 +168,28 @@ named!(parse_code<Code>,
) )
); );
named!(parse_severity<Severity>,
alt!(
tag!("2") => { |_| Severity::PositiveCompletion } |
tag!("3") => { |_| Severity::PositiveIntermediate } |
tag!("4") => { |_| Severity::TransientNegativeCompletion } |
tag!("5") => { |_| Severity::PermanentNegativeCompletion }
)
);
named!(parse_category<Category>,
alt!(
tag!("0") => { |_| Category::Syntax } |
tag!("1") => { |_| Category::Information } |
tag!("2") => { |_| Category::Connections } |
tag!("3") => { |_| Category::Unspecified3 } |
tag!("4") => { |_| Category::Unspecified4 } |
tag!("5") => { |_| Category::MailSystem }
)
);
named!(parse_detail<Detail>, named!(parse_detail<Detail>,
complete!(alt!( alt!(
tag!("0") => { |_| Detail(0) } | tag!("0") => { |_| Detail(0) } |
tag!("1") => { |_| Detail(1) } | tag!("1") => { |_| Detail(1) } |
tag!("2") => { |_| Detail(2) } | tag!("2") => { |_| Detail(2) } |
@@ -229,27 +200,7 @@ named!(parse_detail<Detail>,
tag!("7") => { |_| Detail(7) } | tag!("7") => { |_| Detail(7) } |
tag!("8") => { |_| Detail(8) } | tag!("8") => { |_| Detail(8) } |
tag!("9") => { |_| Detail(9) } tag!("9") => { |_| Detail(9) }
)) )
);
named!(parse_severity<Severity>,
complete!(alt!(
tag!("2") => { |_| Severity::PositiveCompletion } |
tag!("3") => { |_| Severity::PositiveIntermediate } |
tag!("4") => { |_| Severity::TransientNegativeCompletion } |
tag!("5") => { |_| Severity::PermanentNegativeCompletion }
))
);
named!(parse_category<Category>,
complete!(alt!(
tag!("0") => { |_| Category::Syntax } |
tag!("1") => { |_| Category::Information } |
tag!("2") => { |_| Category::Connections } |
tag!("3") => { |_| Category::Unspecified3 } |
tag!("4") => { |_| Category::Unspecified4 } |
tag!("5") => { |_| Category::MailSystem }
))
); );
named!(parse_response<Response>, named!(parse_response<Response>,
@@ -308,32 +259,11 @@ named!(parse_response<Response>,
mod test { mod test {
use super::{Category, Code, Detail, Response, Severity}; use super::{Category, Code, Detail, Response, Severity};
#[test]
fn test_severity_from_str() {
assert_eq!(
"2".parse::<Severity>().unwrap(),
Severity::PositiveCompletion
);
assert_eq!(
"4".parse::<Severity>().unwrap(),
Severity::TransientNegativeCompletion
);
assert!("1".parse::<Severity>().is_err());
assert!("a51".parse::<Severity>().is_err());
}
#[test] #[test]
fn test_severity_fmt() { fn test_severity_fmt() {
assert_eq!(format!("{}", Severity::PositiveCompletion), "2"); assert_eq!(format!("{}", Severity::PositiveCompletion), "2");
} }
#[test]
fn test_category_from_str() {
assert_eq!("2".parse::<Category>().unwrap(), Category::Connections);
assert_eq!("4".parse::<Category>().unwrap(), Category::Unspecified4);
assert!("6".parse::<Category>().is_err());
}
#[test] #[test]
fn test_category_fmt() { fn test_category_fmt() {
assert_eq!(format!("{}", Category::Unspecified4), "4"); assert_eq!(format!("{}", Category::Unspecified4), "4");
@@ -365,24 +295,6 @@ mod test {
); );
} }
#[test]
fn test_code_from_str() {
assert_eq!(
"421".parse::<Code>().unwrap(),
Code {
severity: Severity::TransientNegativeCompletion,
category: Category::Connections,
detail: "1".parse::<Detail>().unwrap(),
}
);
assert!("r2222".parse::<Code>().is_err());
assert!("aaa".parse::<Code>().is_err());
assert!("-32".parse::<Code>().is_err());
assert!("-333".parse::<Code>().is_err());
assert!("".parse::<Code>().is_err());
assert!("9292".parse::<Code>().is_err());
}
#[test] #[test]
fn test_code_display() { fn test_code_display() {
let code = Code { let code = Code {
@@ -395,50 +307,33 @@ mod test {
} }
#[test] #[test]
fn test_response_new() { fn test_response_from_str() {
let raw_response = "250-me\r\n250-8BITMIME\r\n250-SIZE 42\r\n250 AUTH PLAIN CRAM-MD5\r\n";
assert_eq!( assert_eq!(
Response::new( raw_response.parse::<Response>().unwrap(),
Code {
severity: "2".parse::<Severity>().unwrap(),
category: "4".parse::<Category>().unwrap(),
detail: "1".parse::<Detail>().unwrap(),
},
vec![
"me".to_string(),
"8BITMIME".to_string(),
"SIZE 42".to_string(),
],
),
Response { Response {
code: Code { code: Code {
severity: Severity::PositiveCompletion, severity: Severity::PositiveCompletion,
category: Category::Unspecified4, category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(0),
}, },
message: vec![ message: vec![
"me".to_string(), "me".to_string(),
"8BITMIME".to_string(), "8BITMIME".to_string(),
"SIZE 42".to_string(), "SIZE 42".to_string(),
"AUTH PLAIN CRAM-MD5".to_string(),
], ],
} }
); );
assert_eq!(
Response::new( let wrong_code = "2506-me\r\n250-8BITMIME\r\n250-SIZE 42\r\n250 AUTH PLAIN CRAM-MD5\r\n";
Code { assert!(
severity: "2".parse::<Severity>().unwrap(), wrong_code.parse::<Response>().is_err()
category: "4".parse::<Category>().unwrap(), );
detail: "1".parse::<Detail>().unwrap(),
}, let wrong_end = "250-me\r\n250-8BITMIME\r\n250-SIZE 42\r\n250-AUTH PLAIN CRAM-MD5\r\n";
vec![], assert!(
), wrong_end.parse::<Response>().is_err()
Response {
code: Code {
severity: Severity::PositiveCompletion,
category: Category::Unspecified4,
detail: "1".parse::<Detail>().unwrap(),
},
message: vec![],
}
); );
} }
@@ -447,9 +342,9 @@ mod test {
assert!( assert!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::PositiveCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(0),
}, },
vec![ vec![
"me".to_string(), "me".to_string(),
@@ -459,11 +354,11 @@ mod test {
).is_positive() ).is_positive()
); );
assert!(!Response::new( assert!(!Response::new(
Code { Code {
severity: "5".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(0),
}, },
vec![ vec![
"me".to_string(), "me".to_string(),
"8BITMIME".to_string(), "8BITMIME".to_string(),
@@ -477,29 +372,29 @@ mod test {
assert!( assert!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "4".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![ vec![
"me".to_string(), "me".to_string(),
"8BITMIME".to_string(), "8BITMIME".to_string(),
"SIZE 42".to_string(), "SIZE 42".to_string(),
], ],
).has_code(241) ).has_code(451)
); );
assert!(!Response::new( assert!(!Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "5".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![ vec![
"me".to_string(), "me".to_string(),
"8BITMIME".to_string(), "8BITMIME".to_string(),
"SIZE 42".to_string(), "SIZE 42".to_string(),
], ],
).has_code(241)); ).has_code(251));
} }
#[test] #[test]
@@ -507,9 +402,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![ vec![
"me".to_string(), "me".to_string(),
@@ -522,9 +417,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![ vec![
"me mo".to_string(), "me mo".to_string(),
@@ -537,9 +432,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![], vec![],
).first_word(), ).first_word(),
@@ -548,9 +443,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![" ".to_string()], vec![" ".to_string()],
).first_word(), ).first_word(),
@@ -559,9 +454,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![" ".to_string()], vec![" ".to_string()],
).first_word(), ).first_word(),
@@ -570,9 +465,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec!["".to_string()], vec!["".to_string()],
).first_word(), ).first_word(),
@@ -585,9 +480,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![ vec![
"me".to_string(), "me".to_string(),
@@ -600,9 +495,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![ vec![
"me mo".to_string(), "me mo".to_string(),
@@ -615,9 +510,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![], vec![],
).first_line(), ).first_line(),
@@ -626,9 +521,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![" ".to_string()], vec![" ".to_string()],
).first_line(), ).first_line(),
@@ -637,9 +532,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec![" ".to_string()], vec![" ".to_string()],
).first_line(), ).first_line(),
@@ -648,9 +543,9 @@ mod test {
assert_eq!( assert_eq!(
Response::new( Response::new(
Code { Code {
severity: "2".parse::<Severity>().unwrap(), severity: Severity::TransientNegativeCompletion,
category: "3".parse::<Category>().unwrap(), category: Category::MailSystem,
detail: "1".parse::<Detail>().unwrap(), detail: Detail(1),
}, },
vec!["".to_string()], vec!["".to_string()],
).first_line(), ).first_line(),