From d9019e408e5422c34af728ab4ea1e096d65da502 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 21 Nov 2015 17:28:46 +0100 Subject: [PATCH 1/8] Remove static livetime in ParserError::short() --- src/storage/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage/parser.rs b/src/storage/parser.rs index c7df264c..ba5afc3b 100644 --- a/src/storage/parser.rs +++ b/src/storage/parser.rs @@ -22,7 +22,7 @@ impl ParserError { } } - pub fn short(sum: &'static str, text: String, idx: i32) -> ParserError { + pub fn short(sum: &str, text: String, idx: i32) -> ParserError { ParserError { summary: String::from(sum), parsertext: text, From 84e710022969da15f7fff482c0ae36a1e26cb08e Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 21 Nov 2015 17:29:04 +0100 Subject: [PATCH 2/8] Add test for deserialization --- src/storage/json/parser.rs | 64 +++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/src/storage/json/parser.rs b/src/storage/json/parser.rs index ee230620..d0e751f0 100644 --- a/src/storage/json/parser.rs +++ b/src/storage/json/parser.rs @@ -6,6 +6,7 @@ use serde::ser::Serializer as Ser; use std::collections::HashMap; use std::io::stdout; +use std::error::Error; use super::super::parser::{FileHeaderParser, ParserError}; use super::super::file::{FileHeaderSpec, FileHeaderData}; @@ -34,11 +35,13 @@ impl FileHeaderParser for JsonHeaderParser { let s = string.unwrap(); debug!("Deserializing: {}", s); let fromstr : R = from_str(&s[..]); - if let Ok(content) = fromstr { - Ok(visit_json(&content)) - } else { - Err(ParserError::short("Unknown JSON parser error", s.clone(), 0)) + if let Ok(ref content) = fromstr { + return Ok(visit_json(&content)) } + let oe = fromstr.err().unwrap(); + let s = format!("JSON parser error: {}", oe.description()); + let e = ParserError::short(&s[..], s.clone(), 0); + Err(e) } else { Ok(FileHeaderData::Null) } @@ -122,3 +125,56 @@ impl Serialize for FileHeaderData { } } + +#[cfg(test)] +mod test { + + use super::JsonHeaderParser; + use storage::parser::{FileHeaderParser, ParserError}; + use storage::file::{FileHeaderSpec, FileHeaderData}; + + #[test] + fn test_deserialization() { + use storage::file::FileHeaderData as FHD; + use storage::file::FileHeaderSpec as FHS; + + let text = String::from("{\"a\": 1, \"b\": -2}"); + let spec = FHS::Map { + keys: vec![ + FHS::Key { + name: String::from("a"), + value_type: Box::new(FHS::UInteger) + }, + FHS::Key { + name: String::from("b"), + value_type: Box::new(FHS::Integer) + } + ] + }; + + let parser = JsonHeaderParser::new(Some(spec)); + let parsed = parser.read(Some(text)); + assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed); + + match parsed.ok() { + Some(FHD::Map{keys: keys}) => { + for k in keys { + match k { + FHD::Key{name: name, value: box value} => { + assert!(name == "a" || name == "b", "Key unknown"); + match &value { + &FHD::UInteger(u) => assert_eq!(u, 1), + &FHD::Integer(i) => assert_eq!(i, -2), + _ => assert!(false, "Integers are not here"), + } + }, + _ => assert!(false, "Key is not a Key"), + } + } + }, + + _ => assert!(false, "Parsed is not a map"), + } + } + +} From 2dce3151bd26af26994bbe7ef9080f4a67ba96b0 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 21 Nov 2015 17:29:26 +0100 Subject: [PATCH 3/8] Remove default impl for Error for ParserError --- src/storage/parser.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/storage/parser.rs b/src/storage/parser.rs index ba5afc3b..d55b7e70 100644 --- a/src/storage/parser.rs +++ b/src/storage/parser.rs @@ -38,10 +38,6 @@ impl Error for ParserError { &self.summary[..] } - fn cause(&self) -> Option<&Error> { - None - } - } impl Debug for ParserError { From 74a9523f45bf5a65314518c6ef2346c512b84e6b Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 21 Nov 2015 17:53:13 +0100 Subject: [PATCH 4/8] Use box_patterns, so we can unbox in the tests --- src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.rs b/src/main.rs index ea9332fe..ce8e3cdb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![feature(box_patterns)] + #[macro_use] extern crate clap; #[macro_use] extern crate log; #[macro_use] extern crate serde; From 3e75117d69eb81b1c7e29d66cf40cc12be05e4b7 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 3 Dec 2015 11:36:44 +0100 Subject: [PATCH 5/8] Add test: Deserialization without Specification should match as well --- src/storage/json/parser.rs | 64 +++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/src/storage/json/parser.rs b/src/storage/json/parser.rs index d0e751f0..a6a6cf60 100644 --- a/src/storage/json/parser.rs +++ b/src/storage/json/parser.rs @@ -131,13 +131,11 @@ mod test { use super::JsonHeaderParser; use storage::parser::{FileHeaderParser, ParserError}; - use storage::file::{FileHeaderSpec, FileHeaderData}; + use storage::file::FileHeaderData as FHD; + use storage::file::FileHeaderSpec as FHS; #[test] fn test_deserialization() { - use storage::file::FileHeaderData as FHD; - use storage::file::FileHeaderSpec as FHS; - let text = String::from("{\"a\": 1, \"b\": -2}"); let spec = FHS::Map { keys: vec![ @@ -177,4 +175,62 @@ mod test { } } + #[test] + fn test_deserialization_without_spec() { + let text = String::from("{\"a\": [1], \"b\": {\"c\": -2}}"); + let parser = JsonHeaderParser::new(None); + let parsed = parser.read(Some(text)); + + assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed); + + match parsed.ok() { + Some(FHD::Map{keys: keys}) => { + for k in keys { + match_key(&k); + } + }, + + _ => assert!(false, "Parsed is not a map"), + } + } + + fn match_key(k: &FHD) { + use std::ops::Deref; + + match k { + &FHD::Key{name: ref name, value: ref value} => { + assert!(name == "a" || name == "b", "Key unknown"); + match value.deref() { + &FHD::Array{values: ref vs} => { + for value in vs.iter() { + match value { + &FHD::UInteger(u) => assert_eq!(u, 1), + _ => assert!(false, "UInt is not an UInt"), + } + } + } + + &FHD::Map{keys: ref ks} => { + for key in ks.iter() { + match key { + &FHD::Key{name: ref name, value: ref value} => { + match value.deref() { + &FHD::Integer(i) => { + assert_eq!(i, -2); + assert_eq!(name, "c"); + }, + _ => assert!(false, "Int is not an Int"), + }; + }, + _ => assert!(false, "Key is not a Key"), + } + } + } + _ => assert!(false, "Integers are not here"), + } + }, + _ => assert!(false, "Key in main Map is not a Key"), + } + } + } From 04443b34bf301d2a42ab36f31f316c57393a07a6 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 3 Dec 2015 11:57:56 +0100 Subject: [PATCH 6/8] Add test: serialize-deserialize-compare --- src/storage/json/parser.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/storage/json/parser.rs b/src/storage/json/parser.rs index a6a6cf60..40675583 100644 --- a/src/storage/json/parser.rs +++ b/src/storage/json/parser.rs @@ -233,4 +233,26 @@ mod test { } } + #[test] + fn test_desser() { + use serde_json::error::Result as R; + use serde_json::{Value, from_str}; + + let text = String::from("{\"a\": [1], \"b\": {\"c\": -2}}"); + let parser = JsonHeaderParser::new(None); + + let des = parser.read(Some(text.clone())); + assert!(des.is_ok(), "Deserializing failed"); + + let ser = parser.write(&des.unwrap()); + assert!(ser.is_ok(), "Parser error when serializing deserialized text"); + + let json_text : R = from_str(&text[..]); + let json_ser : R = from_str(&ser.unwrap()[..]); + + assert!(json_text.is_ok(), "Could not use serde to serialize text for comparison"); + assert!(json_ser.is_ok(), "Could not use serde to serialize serialized-deserialized text for comparison"); + assert_eq!(json_text.unwrap(), json_ser.unwrap()); + } + } From e025cf88359bdae0e5e24a8871f3e732c282b139 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 3 Dec 2015 12:09:13 +0100 Subject: [PATCH 7/8] Add missing Clone for FileHeaderSpec --- src/storage/file.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/storage/file.rs b/src/storage/file.rs index bf28103c..a45c2292 100644 --- a/src/storage/file.rs +++ b/src/storage/file.rs @@ -9,6 +9,7 @@ use storage::file_id::*; use regex::Regex; #[derive(Debug)] +#[derive(Clone)] pub enum FileHeaderSpec { Null, Bool, From 2ab025a4eb60d289ef23988afe26b546870a10fe Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 3 Dec 2015 12:19:08 +0100 Subject: [PATCH 8/8] Add test: match_header_spec() testing --- src/storage/file.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/storage/file.rs b/src/storage/file.rs index a45c2292..da7dd66e 100644 --- a/src/storage/file.rs +++ b/src/storage/file.rs @@ -329,3 +329,39 @@ impl<'a> Debug for File<'a> { } } + +#[cfg(test)] +mod test { + // we use the JSON parser here, so we can generate FileHeaderData + use storage::json::parser::JsonHeaderParser; + use super::match_header_spec; + use storage::parser::{FileHeaderParser, ParserError}; + use storage::file::FileHeaderData as FHD; + use storage::file::FileHeaderSpec as FHS; + + #[test] + fn test_spec_matching() { + let text = String::from("{\"a\": 1, \"b\": -2}"); + let spec = FHS::Map { + keys: vec![ + FHS::Key { + name: String::from("a"), + value_type: Box::new(FHS::UInteger) + }, + FHS::Key { + name: String::from("b"), + value_type: Box::new(FHS::Integer) + } + ] + }; + + let parser = JsonHeaderParser::new(Some(spec.clone())); + let datares = parser.read(Some(text.clone())); + assert!(datares.is_ok(), "Text could not be parsed: '{}'", text); + let data = datares.unwrap(); + + let matchres = match_header_spec(&spec, &data); + assert!(matchres.is_none(), "Matching returns error: {:?}", matchres); + } +} +