diff --git a/imag-link/Cargo.toml b/imag-link/Cargo.toml index 0f6d8d51..85ed1582 100644 --- a/imag-link/Cargo.toml +++ b/imag-link/Cargo.toml @@ -37,3 +37,8 @@ path = "../libimagerror" [dependencies.libimagutil] path = "../libimagutil" +[dev-dependencies.libimagutil] +path = "../libimagutil" +default-features = false +features = ["testing"] + diff --git a/imag-link/src/main.rs b/imag-link/src/main.rs index f3dc6ca4..76b03cc4 100644 --- a/imag-link/src/main.rs +++ b/imag-link/src/main.rs @@ -44,6 +44,9 @@ extern crate libimagentrylink; extern crate libimagrt; extern crate libimagstore; extern crate libimagerror; + +#[allow(unused_imports)] +#[macro_use] extern crate libimagutil; use std::ops::Deref; @@ -342,79 +345,24 @@ mod tests { use std::path::PathBuf; use std::ffi::OsStr; - use clap::{App, ArgMatches}; use toml::value::Value; use toml_query::read::TomlValueReadExt; use toml_query::error::Result as TomlQueryResult; - use libimagrt::spec::CliSpec; use libimagrt::runtime::Runtime; - use libimagrt::error::RuntimeError; - use libimagrt::configuration::{Configuration, InternalConfiguration}; - use libimagstore::storeid::StoreId; use libimagstore::store::{Result as StoreResult, FileLockEntry}; - static DEFAULT_ENTRY: &'static str = "\ ----\ -[imag]\ -links = []\ -version = \"0.3.0\"\ ----"; - - #[derive(Clone)] - struct MockLinkApp<'a> { - args: Vec<&'static str>, - inner: App<'a, 'a>, + make_mock_app! { + app "imag-link"; + modulename mock; + version "0.3.0"; + with help "imag-link mocking app"; } + use self::mock::generate_test_runtime; + use libimagutil::testing::DEFAULT_ENTRY; - impl<'a> MockLinkApp<'a> { - fn new(args: Vec<&'static str>) -> Self { - MockLinkApp { - args: args, - inner: ::build_ui(Runtime::get_default_cli_builder("imag-link", - "0.3.0", - "Link entries test")), - } - } - } - - impl<'a> CliSpec<'a> for MockLinkApp<'a> { - fn name(&self) -> &str { - self.inner.get_name() - } - - fn matches(self) -> ArgMatches<'a> { - self.inner.get_matches_from(self.args) - } - } - - impl<'a> InternalConfiguration for MockLinkApp<'a> { - fn enable_logging(&self) -> bool { - false - } - - fn use_inmemory_fs(&self) -> bool { - true - } - } - - fn generate_test_config() -> Option { - ::toml::de::from_str("[store]\nimplicit-create=true") - .map(Configuration::with_value) - .ok() - } - - fn generate_test_runtime<'a>(mut args: Vec<&'static str>) -> Result, RuntimeError> { - let mut cli_args = vec!["imag-link", "--rtp", "/tmp"]; - - cli_args.append(&mut args); - - let cli_app = MockLinkApp::new(cli_args); - Runtime::with_configuration(cli_app, generate_test_config()) - } - - fn create_test_entry<'a, S: AsRef>(rt: &'a Runtime, name: S) -> StoreResult { + fn create_test_default_entry<'a, S: AsRef>(rt: &'a Runtime, name: S) -> StoreResult { let mut path = PathBuf::new(); path.set_file_name(name); @@ -441,8 +389,8 @@ version = \"0.3.0\"\ let rt = generate_test_runtime(vec!["internal", "add", "--from", "test1", "--to", "test2"]) .unwrap(); - let test_id1 = create_test_entry(&rt, "test1").unwrap(); - let test_id2 = create_test_entry(&rt, "test2").unwrap(); + let test_id1 = create_test_default_entry(&rt, "test1").unwrap(); + let test_id2 = create_test_default_entry(&rt, "test2").unwrap(); handle_internal_linking(&rt); @@ -461,8 +409,8 @@ version = \"0.3.0\"\ let rt = generate_test_runtime(vec!["internal", "add", "--from", "test1", "--to", "test2"]) .unwrap(); - let test_id1 = create_test_entry(&rt, "test1").unwrap(); - let test_id2 = create_test_entry(&rt, "test2").unwrap(); + let test_id1 = create_test_default_entry(&rt, "test1").unwrap(); + let test_id2 = create_test_default_entry(&rt, "test2").unwrap(); handle_internal_linking(&rt); @@ -481,8 +429,8 @@ version = \"0.3.0\"\ let rt = generate_test_runtime(vec!["internal", "add", "--from", "test1", "--to", "test2"]) .unwrap(); - let test_id1 = create_test_entry(&rt, "test1").unwrap(); - let test_id2 = create_test_entry(&rt, "test2").unwrap(); + let test_id1 = create_test_default_entry(&rt, "test1").unwrap(); + let test_id2 = create_test_default_entry(&rt, "test2").unwrap(); handle_internal_linking(&rt); handle_internal_linking(&rt); diff --git a/libimagutil/Cargo.toml b/libimagutil/Cargo.toml index e9d7a1fd..d732e394 100644 --- a/libimagutil/Cargo.toml +++ b/libimagutil/Cargo.toml @@ -13,6 +13,12 @@ documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.h repository = "https://github.com/matthiasbeyer/imag" homepage = "http://imag-pim.org" +[features] +default = [] + +# Testing feature to compile testing utilities into the library. +testing = [] + [dependencies] url = "1.2" boolinator = "2.4.0" diff --git a/libimagutil/src/lib.rs b/libimagutil/src/lib.rs index c0f71636..b5d30f51 100644 --- a/libimagutil/src/lib.rs +++ b/libimagutil/src/lib.rs @@ -49,3 +49,7 @@ pub mod key_value_split; pub mod variants; pub mod warn_exit; pub mod warn_result; + +#[cfg(feature = "testing")] +pub mod testing; + diff --git a/libimagutil/src/testing.rs b/libimagutil/src/testing.rs new file mode 100644 index 00000000..cb36a4a5 --- /dev/null +++ b/libimagutil/src/testing.rs @@ -0,0 +1,115 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +pub static DEFAULT_ENTRY: &'static str = "\ +---\ +[imag]\ +links = []\ +version = \"0.3.0\"\ +---"; + +/// Generator helper macro for mock app (for testing only) +/// +/// Requires the following crates in scope: +/// +/// * std +/// * libimagrt +/// * clap +/// +#[macro_export] +macro_rules! make_mock_app { + { + app $appname:expr; + module $module:ident; + version $version:expr; + } => { + make_mock_app! { + app $appname; + module $module; + version $version; + with help "This is a mocking app"; + } + }; + + { + app $appname:expr; + modulename $module:ident; + version $version:expr; + with help $help:expr; + }=> { + mod $module { + use clap::{App, ArgMatches}; + use libimagrt::spec::CliSpec; + use libimagrt::runtime::Runtime; + use libimagrt::error::RuntimeError; + use libimagrt::configuration::{Configuration, InternalConfiguration}; + + #[derive(Clone)] + struct MockLinkApp<'a> { + args: Vec<&'static str>, + inner: App<'a, 'a>, + } + + impl<'a> MockLinkApp<'a> { + fn new(args: Vec<&'static str>) -> Self { + MockLinkApp { + args: args, + inner: ::build_ui(Runtime::get_default_cli_builder($appname, $version, $help)), + } + } + } + + impl<'a> CliSpec<'a> for MockLinkApp<'a> { + fn name(&self) -> &str { + self.inner.get_name() + } + + fn matches(self) -> ArgMatches<'a> { + self.inner.get_matches_from(self.args) + } + } + + impl<'a> InternalConfiguration for MockLinkApp<'a> { + fn enable_logging(&self) -> bool { + false + } + + fn use_inmemory_fs(&self) -> bool { + true + } + } + + pub fn generate_minimal_test_config() -> Option { ::toml::de::from_str("[store]\nimplicit-create=true") + .map(Configuration::with_value) + .ok() + } + + pub fn generate_test_runtime<'a>(mut args: Vec<&'static str>) -> Result, RuntimeError> { + let mut cli_args = vec!["imag-link", "--rtp", "/tmp"]; + + cli_args.append(&mut args); + + let cli_app = MockLinkApp::new(cli_args); + Runtime::with_configuration(cli_app, generate_minimal_test_config()) + } + } + }; + +} +