diff --git a/src/lib.rs b/src/lib.rs index d1af4005b..309f4b920 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,11 +38,22 @@ mod visitors; mod writer; mod xmlparser; -pub use analysis::run as analysis_run; pub use analysis::class_hierarchy::run as class_hierarchy_run; pub use analysis::namespaces::run as namespaces_run; +pub use analysis::run as analysis_run; pub use analysis::symbols::run as symbols_run; pub use codegen::generate as codegen_generate; pub use config::{Config, WorkMode}; pub use env::Env; pub use library::Library; + +pub mod tests_export { + pub use config::gobjects::{GObject, GObjects}; + pub use traits::*; + pub use version::Version; + + pub mod library { + pub use library::*; + pub use parser::EMPTY_CTYPE; + } +} diff --git a/src/parser.rs b/src/parser.rs index 98efd7848..c063b8c86 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,3 +1,4 @@ +use std::io::Read; use std::mem::replace; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -6,7 +7,7 @@ use library::*; use version::Version; use xmlparser::{Element, XmlParser}; -const EMPTY_CTYPE: &str = "/*EMPTY*/"; +pub const EMPTY_CTYPE: &str = "/*EMPTY*/"; pub fn is_empty_c_type(c_type: &str) -> bool { c_type == EMPTY_CTYPE @@ -23,6 +24,16 @@ impl Library { }) } + pub fn read_reader(&mut self, reader: R) -> Result<(), String> { + let dir = Path::new("read_reader_not_implement_include"); + let mut p = XmlParser::new(reader)?; + p.document(|p, _| { + p.element_with_name("repository", |parser, _elem| { + self.read_repository(dir, parser) + }) + }) + } + fn read_repository(&mut self, dir: &Path, parser: &mut XmlParser) -> Result<(), String> { let mut package = None; let mut includes = Vec::new(); @@ -48,8 +59,12 @@ impl Library { } Ok(()) } - "namespace" => self.read_namespace(parser, elem, package.take(), - replace(&mut includes, Vec::new())), + "namespace" => self.read_namespace( + parser, + elem, + package.take(), + replace(&mut includes, Vec::new()), + ), _ => Err(parser.unexpected_element(elem)), })?; Ok(()) diff --git a/src/xmlparser.rs b/src/xmlparser.rs index 078de276e..1f14b8239 100644 --- a/src/xmlparser.rs +++ b/src/xmlparser.rs @@ -145,7 +145,6 @@ impl<'a> XmlParser<'a> { } } - #[cfg(test)] pub fn new<'r, R: 'r + Read>(read: R) -> Result, String> { Ok(XmlParser { parser: EventReader::new(Box::new(read)), diff --git a/tests/read_library.rs b/tests/read_library.rs new file mode 100644 index 000000000..afb00b7a5 --- /dev/null +++ b/tests/read_library.rs @@ -0,0 +1,194 @@ +//! This test module contains tests that use files read_library\*.gir for checking library load + +extern crate libgir as gir; + +mod test_util; + +use std::fs::File; +use std::io::{self, Read}; +use std::path::Path; + +use gir::tests_export::*; +use test_util::*; + +fn read_library>(filename: P) -> Result<(library::Library), io::Error> { + let full_name = Path::new("tests") + .join("read_library") + .join(filename.as_ref()); + let cfg = create_default_config(); + let mut library = library::Library::new(&cfg.library_name); + let (f, _) = read_parameterized(full_name)?; + library.read_reader(f).unwrap(); + Ok(library) +} + +#[test] +fn load_normal() { + let cfg = create_default_config(); + let mut library = library::Library::new(&cfg.library_name); + + let f = File::open("tests/read_library/normal.gir").unwrap(); + library.read_reader(f).unwrap(); + assert!(library.find_type(1, "TimeSpan").is_some()); +} + +#[test] +fn read_mode_default() { + let (mut f, _) = read_parameterized("tests/read_library/normal.gir").unwrap(); + let mut buffer = vec![0u8; 6]; + assert_eq!(f.read(&mut buffer).unwrap(), 6); + let str = String::from_utf8_lossy(&buffer); + assert_eq!(str, " + + + diff --git a/tests/read_library/bitfield.gir b/tests/read_library/bitfield.gir new file mode 100644 index 000000000..35ccb6364 --- /dev/null +++ b/tests/read_library/bitfield.gir @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/read_library/class.gir b/tests/read_library/class.gir new file mode 100644 index 000000000..6bfa51ce2 --- /dev/null +++ b/tests/read_library/class.gir @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/read_library/constant.gir b/tests/read_library/constant.gir new file mode 100644 index 000000000..e70755bb2 --- /dev/null +++ b/tests/read_library/constant.gir @@ -0,0 +1,4 @@ + + + + diff --git a/tests/read_library/enumeration.gir b/tests/read_library/enumeration.gir new file mode 100644 index 000000000..83463fe93 --- /dev/null +++ b/tests/read_library/enumeration.gir @@ -0,0 +1,8 @@ + + + Error codes returned by bookmark file parsing. + + + + + diff --git a/tests/read_library/function.gir b/tests/read_library/function.gir new file mode 100644 index 000000000..2db1afd85 --- /dev/null +++ b/tests/read_library/function.gir @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tests/read_library/mode_full.gir b/tests/read_library/mode_full.gir new file mode 100644 index 000000000..7003a9b65 --- /dev/null +++ b/tests/read_library/mode_full.gir @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tests/read_library/mode_object.gir b/tests/read_library/mode_object.gir new file mode 100644 index 000000000..4a1a09bd5 --- /dev/null +++ b/tests/read_library/mode_object.gir @@ -0,0 +1,4 @@ + + + + diff --git a/tests/read_library/normal.gir b/tests/read_library/normal.gir new file mode 100644 index 000000000..e3ae43484 --- /dev/null +++ b/tests/read_library/normal.gir @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tests/test_util/mod.rs b/tests/test_util/mod.rs new file mode 100644 index 000000000..789069c8a --- /dev/null +++ b/tests/test_util/mod.rs @@ -0,0 +1,106 @@ +//! This submodule module is used in intergation tests and contains helpers + +extern crate libgir as gir; + +use std::collections::HashMap; +use std::fs::File; +use std::io::{self, BufRead, BufReader, Read, Seek, SeekFrom}; +use std::path::Path; +use std::str::FromStr; + +use gir::tests_export::*; +use gir::*; + +pub fn create_default_config() -> Config { + let objects: GObjects = Default::default(); + Config { + work_mode: WorkMode::Normal, + girs_dir: "tmp1".into(), + girs_version: "test".into(), + library_name: "Tst".into(), + library_version: "1.0".into(), + target_path: "tmp2".into(), + doc_target_path: "tmp2".into(), + external_libraries: Default::default(), + objects, + min_cfg_version: Version::from_str("0").unwrap(), + make_backup: false, + generate_safety_asserts: true, + deprecate_by_min_version: true, + show_statistics: false, + concurrency: library::Concurrency::None, + single_version_file: None, + } +} + +pub type Parameters = HashMap; + +/// Read .gir file. +/// If file begins with comments, these comments are converted +/// to parameters in format name:value +/// Internally support "mode" parameter with next values: +/// "full" - file readed without changes, +/// "object" - file content is framed with repository/namespace +pub fn read_parameterized>( + filename: P, +) -> Result<(Box, Parameters), io::Error> { + const COMMENT_START: &str = ""; + + let filename = filename.as_ref(); + let f = File::open(filename)?; + let mut f = BufReader::new(f); + + let mut params = Parameters::new(); + params.insert("mode".into(), "full".into()); + + let mut line = String::new(); + loop { + line.clear(); + let readed = f.read_line(&mut line)?; + if readed == 0 { + break; + } + if !line.starts_with(COMMENT_START) { + f.seek(SeekFrom::Current(-(readed as i64)))?; + break; + } + let mut split = line.split(':'); + let name = split.next().unwrap(); + let name = name.trim_left_matches(COMMENT_START); + let value = split.next().expect("No name:value in comment"); + let value = value.trim_right().trim_right_matches(COMMENT_END); + assert!(split.next().is_none(), "Multiple : in comment"); + params.insert(name.into(), value.into()); + } + + let mode = params.get("mode").unwrap().to_owned(); + match mode.as_str() { + "full" => Ok((Box::new(f), params)), + "object" => { + let begin = r##" + + + +"## + .as_bytes(); + let end = r##" +"## + .as_bytes(); + Ok((Box::new(begin.chain(f).chain(end)), params)) + } + _ => panic!("unsupported mode {}", mode), + } +} + +/// Get type in main namespace +pub fn get_type<'a, T>(library: &'a library::Library, type_name: &str) -> &'a T +where + library::Type: MaybeRef, +{ + library + .find_type(1, type_name) + .map(|t| library.type_(t)) + .map(|t| t.to_ref_as::()) + .expect(&format!("type {} not found", type_name)) +}