From 6be3011e85eb7eec54410a608ab5c0b94ebd98f1 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 18 Jan 2016 14:12:12 +0100 Subject: [PATCH 01/13] Add: EntryHeader::parse() Introduce Error + Error-kind for it, return Result<> from the ::parse() function. --- libimagstore/src/header.rs | 84 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/libimagstore/src/header.rs b/libimagstore/src/header.rs index 9f33e1c9..daa0cc59 100644 --- a/libimagstore/src/header.rs +++ b/libimagstore/src/header.rs @@ -1,5 +1,75 @@ +use std::error::Error; +use std::result::Result as RResult; + use toml::Table; +pub mod error { + use std::fmt::{Debug, Display, Formatter}; + use std::fmt; + use std::error::Error; + use toml; + + #[derive(Clone)] + pub enum ParserErrorKind { + TOMLParserErrors, + MissingMainSection, + } + + pub struct ParserError { + kind: ParserErrorKind, + cause: Option>, + } + + impl ParserError { + + pub fn new(k: ParserErrorKind, cause: Option>) -> ParserError { + ParserError { + kind: k, + cause: cause, + } + } + + } + + impl Debug for ParserError { + + fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { + try!(write!(f, "{:?}", self.description())); + Ok(()) + } + + } + + impl Display for ParserError { + + fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { + try!(write!(f, "{}", self.description())); + Ok(()) + } + + } + + impl Error for ParserError { + + fn description(&self) -> &str { + match self.kind { + ParserErrorKind::MissingMainSection => "Missing main section", + ParserErrorKind::TOMLParserErrors => "Several TOML-Parser-Errors", + } + } + + fn cause(&self) -> Option<&Error> { + self.cause.as_ref().map(|e| &**e) + } + + } + +} + + +use self::error::ParserErrorKind; +use self::error::ParserError; + /** * EntryHeader * @@ -11,6 +81,11 @@ pub struct EntryHeader { toml: Table, } +pub type Result = RResult; + +/** + * Wrapper type around file header (TOML) object + */ impl EntryHeader { /** @@ -29,4 +104,13 @@ impl EntryHeader { &self.toml } + pub fn parse(s: &str) -> Result { + use toml::Parser; + + let mut parser = Parser::new(s); + parser.parse() + .ok_or(ParserError::new(ParserErrorKind::TOMLParserErrors, None)) + .map(|table| EntryHeader::new(table)) + } + } From 3e661439e892b30659c7cc88056cc2db09b09596 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 18 Jan 2016 14:56:37 +0100 Subject: [PATCH 02/13] Add sanity-check to header parsing --- libimagstore/src/header.rs | 41 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/libimagstore/src/header.rs b/libimagstore/src/header.rs index daa0cc59..7766f921 100644 --- a/libimagstore/src/header.rs +++ b/libimagstore/src/header.rs @@ -1,7 +1,7 @@ use std::error::Error; use std::result::Result as RResult; -use toml::Table; +use toml::{Table, Value}; pub mod error { use std::fmt::{Debug, Display, Formatter}; @@ -13,6 +13,7 @@ pub mod error { pub enum ParserErrorKind { TOMLParserErrors, MissingMainSection, + MissingVersionInfo, } pub struct ParserError { @@ -53,8 +54,9 @@ pub mod error { fn description(&self) -> &str { match self.kind { - ParserErrorKind::MissingMainSection => "Missing main section", ParserErrorKind::TOMLParserErrors => "Several TOML-Parser-Errors", + ParserErrorKind::MissingMainSection => "Missing main section", + ParserErrorKind::MissingVersionInfo => "Missing version information in main section", } } @@ -110,7 +112,42 @@ impl EntryHeader { let mut parser = Parser::new(s); parser.parse() .ok_or(ParserError::new(ParserErrorKind::TOMLParserErrors, None)) + .and_then(|table| { + if !has_main_section(&table) { + Err(ParserError::new(ParserErrorKind::MissingMainSection, None)) + } else if !has_imag_version_in_main_section(&table) { + Err(ParserError::new(ParserErrorKind::MissingVersionInfo, None)) + } else { + Ok(table) + } + }) .map(|table| EntryHeader::new(table)) } } + +fn has_main_section(t: &Table) -> bool { + t.contains_key("imag") && + match t.get("imag") { + Some(&Value::Table(_)) => true, + Some(_) => false, + None => false, + } +} + +fn has_imag_version_in_main_section(t: &Table) -> bool { + match t.get("imag").unwrap() { + &Value::Table(ref sec) => { + sec.get("version") + .and_then(|v| { + match v { + &Value::String(_) => Some(true), + _ => Some(false), + } + }) + .unwrap_or(false) + } + _ => false, + } +} + From 2a4f3baf0bffba30e11bbd5d4907f33b4793554d Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 18 Jan 2016 19:42:53 +0100 Subject: [PATCH 03/13] Add tests on header checkers --- libimagstore/src/header.rs | 73 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/libimagstore/src/header.rs b/libimagstore/src/header.rs index 7766f921..a6980a11 100644 --- a/libimagstore/src/header.rs +++ b/libimagstore/src/header.rs @@ -151,3 +151,76 @@ fn has_imag_version_in_main_section(t: &Table) -> bool { } } + +#[cfg(test)] +mod test { + use std::collections::BTreeMap; + + use toml::Value; + + #[test] + fn test_imag_section() { + use super::has_main_section; + + let mut map = BTreeMap::new(); + map.insert("imag".into(), Value::Table(BTreeMap::new())); + + assert!(has_main_section(&map)); + } + + #[test] + fn test_imag_invalid_section_type() { + use super::has_main_section; + + let mut map = BTreeMap::new(); + map.insert("imag".into(), Value::Boolean(false)); + + assert!(!has_main_section(&map)); + } + + #[test] + fn test_imag_abscent_main_section() { + use super::has_main_section; + + let mut map = BTreeMap::new(); + map.insert("not_imag".into(), Value::Boolean(false)); + + assert!(!has_main_section(&map)); + } + + #[test] + fn test_main_section_without_version() { + use super::has_imag_version_in_main_section; + + let mut map = BTreeMap::new(); + map.insert("imag".into(), Value::Table(BTreeMap::new())); + + assert!(!has_imag_version_in_main_section(&map)); + } + + #[test] + fn test_main_section_with_version() { + use super::has_imag_version_in_main_section; + + let mut map = BTreeMap::new(); + let mut sub = BTreeMap::new(); + sub.insert("version".into(), Value::String("0.0.0".into())); + map.insert("imag".into(), Value::Table(sub)); + + assert!(has_imag_version_in_main_section(&map)); + } + + #[test] + fn test_main_section_with_version_in_wrong_type() { + use super::has_imag_version_in_main_section; + + let mut map = BTreeMap::new(); + let mut sub = BTreeMap::new(); + sub.insert("version".into(), Value::Boolean(false)); + map.insert("imag".into(), Value::Table(sub)); + + assert!(!has_imag_version_in_main_section(&map)); + } + +} + From 9884f78dae0a1cbc6e118fd71441c366427ceb00 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 18 Jan 2016 19:46:12 +0100 Subject: [PATCH 04/13] Move header verifying into helper function --- libimagstore/src/header.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/libimagstore/src/header.rs b/libimagstore/src/header.rs index a6980a11..d068ae3b 100644 --- a/libimagstore/src/header.rs +++ b/libimagstore/src/header.rs @@ -112,20 +112,22 @@ impl EntryHeader { let mut parser = Parser::new(s); parser.parse() .ok_or(ParserError::new(ParserErrorKind::TOMLParserErrors, None)) - .and_then(|table| { - if !has_main_section(&table) { - Err(ParserError::new(ParserErrorKind::MissingMainSection, None)) - } else if !has_imag_version_in_main_section(&table) { - Err(ParserError::new(ParserErrorKind::MissingVersionInfo, None)) - } else { - Ok(table) - } - }) - .map(|table| EntryHeader::new(table)) + .and_then(|t| verify_header_consistency(t)) + .map(|t| EntryHeader::new(t)) } } +fn verify_header_consistency(t: Table) -> Result { + if !has_main_section(&t) { + Err(ParserError::new(ParserErrorKind::MissingMainSection, None)) + } else if !has_imag_version_in_main_section(&t) { + Err(ParserError::new(ParserErrorKind::MissingVersionInfo, None)) + } else { + Ok(t) + } +} + fn has_main_section(t: &Table) -> bool { t.contains_key("imag") && match t.get("imag") { From 1187f7d9b335431df336cb72b0dcabc72b35fc84 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 18 Jan 2016 22:17:18 +0100 Subject: [PATCH 05/13] Add header verification test --- libimagstore/src/header.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libimagstore/src/header.rs b/libimagstore/src/header.rs index d068ae3b..5ab517c5 100644 --- a/libimagstore/src/header.rs +++ b/libimagstore/src/header.rs @@ -224,5 +224,22 @@ mod test { assert!(!has_imag_version_in_main_section(&map)); } + #[test] + fn test_verification_good() { + use super::verify_header_consistency; + + let mut header = BTreeMap::new(); + let sub = { + let mut sub = BTreeMap::new(); + sub.insert("version".into(), Value::String(String::from("0.0.0"))); + + Value::Table(sub) + }; + + header.insert("imag".into(), sub); + + assert!(verify_header_consistency(header).is_ok()); + } + } From 775d724a8c32c11c035c994deb583038df342955 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 18 Jan 2016 22:17:50 +0100 Subject: [PATCH 06/13] Add header test: Invalid version string --- libimagstore/src/header.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libimagstore/src/header.rs b/libimagstore/src/header.rs index 5ab517c5..5a086990 100644 --- a/libimagstore/src/header.rs +++ b/libimagstore/src/header.rs @@ -241,5 +241,22 @@ mod test { assert!(verify_header_consistency(header).is_ok()); } + #[test] + fn test_verification_invalid_versionstring() { + use super::verify_header_consistency; + + let mut header = BTreeMap::new(); + let sub = { + let mut sub = BTreeMap::new(); + sub.insert("version".into(), Value::String(String::from("000"))); + + Value::Table(sub) + }; + + header.insert("imag".into(), sub); + + assert!(!verify_header_consistency(header).is_ok()); + } + } From f4fbbb688d11edf313c4ffa2d4827bb9a1242806 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 18 Jan 2016 22:25:40 +0100 Subject: [PATCH 07/13] Add dep: regex --- libimagstore/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libimagstore/Cargo.toml b/libimagstore/Cargo.toml index 4186bf70..ec7de64b 100644 --- a/libimagstore/Cargo.toml +++ b/libimagstore/Cargo.toml @@ -5,8 +5,9 @@ authors = ["Matthias Beyer "] [dependencies] fs2 = "0.2.2" -toml = "0.1.25" +regex = "0.1.47" semver = "0.2" +toml = "0.1.25" [dev-dependencies] tempdir = "0.3.4" From dd11e32d8225b3ad5bb71dda42153dc971f4a4e5 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 18 Jan 2016 22:25:49 +0100 Subject: [PATCH 08/13] Include regex --- libimagstore/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/libimagstore/src/lib.rs b/libimagstore/src/lib.rs index 808bf9fa..60f71154 100644 --- a/libimagstore/src/lib.rs +++ b/libimagstore/src/lib.rs @@ -1,4 +1,5 @@ extern crate fs2; +extern crate regex; extern crate toml; #[cfg(test)] extern crate tempdir; extern crate semver; From b4869607205b5e50add4523b257f8bae6f954458 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 18 Jan 2016 22:26:23 +0100 Subject: [PATCH 09/13] Add version-string verification --- libimagstore/src/header.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libimagstore/src/header.rs b/libimagstore/src/header.rs index 5a086990..74f8b748 100644 --- a/libimagstore/src/header.rs +++ b/libimagstore/src/header.rs @@ -138,12 +138,16 @@ fn has_main_section(t: &Table) -> bool { } fn has_imag_version_in_main_section(t: &Table) -> bool { + use regex::Regex; + match t.get("imag").unwrap() { &Value::Table(ref sec) => { sec.get("version") .and_then(|v| { match v { - &Value::String(_) => Some(true), + &Value::String(ref s) => { + Some(Regex::new(r"^\d{1}\.\d{1}\.\d{1}(.*)").unwrap().is_match(&s[..])) + }, _ => Some(false), } }) From b0859c3e2fb97cedddb25428dc50aa1dbfe52bb9 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 18 Jan 2016 22:34:41 +0100 Subject: [PATCH 10/13] Use semver parser instead of regex --- libimagstore/src/header.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libimagstore/src/header.rs b/libimagstore/src/header.rs index 74f8b748..9cd8362c 100644 --- a/libimagstore/src/header.rs +++ b/libimagstore/src/header.rs @@ -138,7 +138,7 @@ fn has_main_section(t: &Table) -> bool { } fn has_imag_version_in_main_section(t: &Table) -> bool { - use regex::Regex; + use semver::Version; match t.get("imag").unwrap() { &Value::Table(ref sec) => { @@ -146,7 +146,7 @@ fn has_imag_version_in_main_section(t: &Table) -> bool { .and_then(|v| { match v { &Value::String(ref s) => { - Some(Regex::new(r"^\d{1}\.\d{1}\.\d{1}(.*)").unwrap().is_match(&s[..])) + Some(Version::parse(&s[..]).is_ok()) }, _ => Some(false), } From a8ac1593e7172a5ea62a39d881cac7770e7ded41 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 19 Jan 2016 10:34:46 +0100 Subject: [PATCH 11/13] Add dep: version = 1.1.0 --- libimagstore/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/libimagstore/Cargo.toml b/libimagstore/Cargo.toml index ec7de64b..02f99124 100644 --- a/libimagstore/Cargo.toml +++ b/libimagstore/Cargo.toml @@ -8,6 +8,7 @@ fs2 = "0.2.2" regex = "0.1.47" semver = "0.2" toml = "0.1.25" +version = "1.1.0" [dev-dependencies] tempdir = "0.3.4" From e01f70aaadcb3e5b60fac21b57efb67256ef8f87 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 19 Jan 2016 10:37:13 +0100 Subject: [PATCH 12/13] Use version We use this not only for tests, but for the whole crate, as I assume that we might need this crate later on in the non-test sources anyways. --- libimagstore/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/libimagstore/src/lib.rs b/libimagstore/src/lib.rs index 60f71154..69665320 100644 --- a/libimagstore/src/lib.rs +++ b/libimagstore/src/lib.rs @@ -1,3 +1,4 @@ +#[macro_use] extern crate version; extern crate fs2; extern crate regex; extern crate toml; From ffe56c499375846dce3b1fd2416557f7ce5ac08a Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 19 Jan 2016 10:38:01 +0100 Subject: [PATCH 13/13] Add test with current version --- libimagstore/src/header.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libimagstore/src/header.rs b/libimagstore/src/header.rs index 9cd8362c..730798d2 100644 --- a/libimagstore/src/header.rs +++ b/libimagstore/src/header.rs @@ -262,5 +262,24 @@ mod test { assert!(!verify_header_consistency(header).is_ok()); } + + #[test] + fn test_verification_current_version() { + use version; + + use super::verify_header_consistency; + + let mut header = BTreeMap::new(); + let sub = { + let mut sub = BTreeMap::new(); + sub.insert("version".into(), Value::String(version!())); + + Value::Table(sub) + }; + + header.insert("imag".into(), sub); + + assert!(verify_header_consistency(header).is_ok()); + } }