summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-07-19 11:32:43 +0200
committerGitHub <noreply@github.com>2017-07-19 11:32:43 +0200
commite4f8d4ec08cd506de10a5c01d6749bb9a993c603 (patch)
tree7e705aff5d035c55855d50e8de3530331f1e0d98
parentc9360a460abe0faf013d0101659bc594c5d0306c (diff)
parent1567fb0d8e637e91362aa35ea2c41e208f81be45 (diff)
Merge pull request #1001 from matthiasbeyer/imag-tag/tests
imag-tag/tests
-rw-r--r--imag-tag/Cargo.toml9
-rw-r--r--imag-tag/src/main.rs204
-rw-r--r--libimagentrytag/src/lib.rs1
-rw-r--r--libimagentrytag/src/tag.rs5
-rw-r--r--libimagentrytag/src/tagable.rs12
-rw-r--r--libimagentrytag/src/ui.rs3
-rw-r--r--libimagentrytag/src/util.rs24
-rw-r--r--libimagutil/src/cli_validators.rs9
8 files changed, 224 insertions, 43 deletions
diff --git a/imag-tag/Cargo.toml b/imag-tag/Cargo.toml
index 2cdc7823..0388270e 100644
--- a/imag-tag/Cargo.toml
+++ b/imag-tag/Cargo.toml
@@ -35,3 +35,12 @@ path = "../libimagentrytag"
[dependencies.libimagutil]
path = "../libimagutil"
+[dev-dependencies.libimagutil]
+path = "../libimagutil"
+default-features = false
+features = ["testing"]
+
+[dev-dependencies]
+toml-query = "0.3.0"
+env_logger = "0.3"
+
diff --git a/imag-tag/src/main.rs b/imag-tag/src/main.rs
index d0a83725..7e710c9b 100644
--- a/imag-tag/src/main.rs
+++ b/imag-tag/src/main.rs
@@ -27,8 +27,16 @@ extern crate libimagstore;
extern crate libimagrt;
extern crate libimagentrytag;
extern crate libimagerror;
+
+#[macro_use]
extern crate libimagutil;
+#[cfg(test)]
+extern crate toml_query;
+
+#[cfg(test)]
+extern crate env_logger;
+
use std::path::PathBuf;
use libimagrt::runtime::Runtime;
@@ -169,3 +177,199 @@ fn list(id: PathBuf, rt: &Runtime) {
}
}
+#[cfg(test)]
+mod tests {
+ use std::path::PathBuf;
+ use std::ffi::OsStr;
+
+ use toml::value::Value;
+ use toml_query::read::TomlValueReadExt;
+ use toml_query::error::Result as TomlQueryResult;
+
+ use libimagentrytag::ui::{get_add_tags, get_remove_tags};
+ use libimagrt::runtime::Runtime;
+ use libimagstore::storeid::StoreId;
+ use libimagstore::store::{Result as StoreResult, FileLockEntry};
+
+ use super::alter;
+
+ make_mock_app! {
+ app "imag-tag";
+ modulename mock;
+ version "0.3.0";
+ with help "imag-tag mocking app";
+ }
+ use self::mock::generate_test_runtime;
+ use libimagutil::testing::DEFAULT_ENTRY;
+
+ fn create_test_default_entry<'a, S: AsRef<OsStr>>(rt: &'a Runtime, name: S) -> StoreResult<StoreId> {
+ let mut path = PathBuf::new();
+ path.set_file_name(name);
+
+ let id = StoreId::new_baseless(path)?;
+ let mut entry = rt.store().create(id.clone())?;
+ entry.get_content_mut().push_str(DEFAULT_ENTRY);
+
+ Ok(id)
+ }
+
+ fn get_entry_tags<'a>(entry: &'a FileLockEntry<'a>) -> TomlQueryResult<Option<&'a Value>> {
+ entry.get_header().read(&"imag.tags".to_owned())
+ }
+
+ fn tags_toml_value<'a, I: IntoIterator<Item = &'static str>>(tags: I) -> Value {
+ Value::Array(tags.into_iter().map(|s| Value::String(s.to_owned())).collect())
+ }
+
+ fn setup_logging() {
+ use env_logger;
+ let _ = env_logger::init().unwrap_or(());
+ }
+
+ #[test]
+ fn test_tag_add_adds_tag() {
+ setup_logging();
+ debug!("Generating runtime");
+ let rt = generate_test_runtime(vec!["--id", "test", "--add", "foo"]).unwrap();
+
+ debug!("Creating default entry");
+ create_test_default_entry(&rt, "test").unwrap();
+ let id = PathBuf::from(String::from("test"));
+
+ debug!("Getting 'add' tags");
+ let add = get_add_tags(rt.cli());
+ debug!("Add-tags: {:?}", add);
+
+ debug!("Getting 'remove' tags");
+ let rem = get_remove_tags(rt.cli());
+ debug!("Rem-tags: {:?}", rem);
+
+ debug!("Altering things");
+ alter(&rt, id.clone(), add, rem);
+ debug!("Altered");
+
+ let test_entry = rt.store().get(id).unwrap().unwrap();
+ let test_tags = get_entry_tags(&test_entry).unwrap().unwrap();
+
+ assert_ne!(*test_tags, tags_toml_value(vec![]));
+ assert_eq!(*test_tags, tags_toml_value(vec!["foo"]));
+ }
+
+ #[test]
+ fn test_tag_add_more_than_remove_adds_tags() {
+ setup_logging();
+ debug!("Generating runtime");
+ let rt = generate_test_runtime(vec!["--id", "test",
+ "--add", "foo",
+ "--add", "bar",
+ "--add", "baz",
+ "--add", "bub",
+ "--remove", "foo",
+ "--remove", "bar",
+ "--remove", "baz",
+ ]).unwrap();
+
+ debug!("Creating default entry");
+ create_test_default_entry(&rt, "test").unwrap();
+ let id = PathBuf::from(String::from("test"));
+
+ // Manually add tags
+ let add = get_add_tags(rt.cli());
+
+ debug!("Getting 'remove' tags");
+ let rem = get_remove_tags(rt.cli());
+ debug!("Rem-tags: {:?}", rem);
+
+ debug!("Altering things");
+ alter(&rt, id.clone(), add, rem);
+ debug!("Altered");
+
+ let test_entry = rt.store().get(id).unwrap().unwrap();
+ let test_tags = get_entry_tags(&test_entry).unwrap().unwrap();
+
+ assert_eq!(*test_tags, tags_toml_value(vec!["bub"]));
+ }
+
+ #[test]
+ fn test_tag_remove_removes_tag() {
+ setup_logging();
+ debug!("Generating runtime");
+ let rt = generate_test_runtime(vec!["--id", "test", "--remove", "foo"]).unwrap();
+
+ debug!("Creating default entry");
+ create_test_default_entry(&rt, "test").unwrap();
+ let id = PathBuf::from(String::from("test"));
+
+ // Manually add tags
+ let add = Some(vec![ "foo".to_owned() ]);
+
+ debug!("Getting 'remove' tags");
+ let rem = get_remove_tags(rt.cli());
+ debug!("Rem-tags: {:?}", rem);
+
+ debug!("Altering things");
+ alter(&rt, id.clone(), add, rem);
+ debug!("Altered");
+
+ let test_entry = rt.store().get(id).unwrap().unwrap();
+ let test_tags = get_entry_tags(&test_entry).unwrap().unwrap();
+
+ assert_eq!(*test_tags, tags_toml_value(vec![]));
+ }
+
+ #[test]
+ fn test_tag_remove_removes_only_to_remove_tag() {
+ setup_logging();
+ debug!("Generating runtime");
+ let rt = generate_test_runtime(vec!["--id", "test", "--remove", "foo"]).unwrap();
+
+ debug!("Creating default entry");
+ create_test_default_entry(&rt, "test").unwrap();
+ let id = PathBuf::from(String::from("test"));
+
+ // Manually add tags
+ let add = Some(vec![ "foo".to_owned(), "bar".to_owned() ]);
+
+ debug!("Getting 'remove' tags");
+ let rem = get_remove_tags(rt.cli());
+ debug!("Rem-tags: {:?}", rem);
+
+ debug!("Altering things");
+ alter(&rt, id.clone(), add, rem);
+ debug!("Altered");
+
+ let test_entry = rt.store().get(id).unwrap().unwrap();
+ let test_tags = get_entry_tags(&test_entry).unwrap().unwrap();
+
+ assert_eq!(*test_tags, tags_toml_value(vec!["bar"]));
+ }
+
+ #[test]
+ fn test_tag_remove_removes_but_doesnt_crash_on_nonexistent_tag() {
+ setup_logging();
+ debug!("Generating runtime");
+ let rt = generate_test_runtime(vec!["--id", "test", "--remove", "foo", "--remove", "bar"]).unwrap();
+
+ debug!("Creating default entry");
+ create_test_default_entry(&rt, "test").unwrap();
+ let id = PathBuf::from(String::from("test"));
+
+ // Manually add tags
+ let add = Some(vec![ "foo".to_owned() ]);
+
+ debug!("Getting 'remove' tags");
+ let rem = get_remove_tags(rt.cli());
+ debug!("Rem-tags: {:?}", rem);
+
+ debug!("Altering things");
+ alter(&rt, id.clone(), add, rem);
+ debug!("Altered");
+
+ let test_entry = rt.store().get(id).unwrap().unwrap();
+ let test_tags = get_entry_tags(&test_entry).unwrap().unwrap();
+
+ assert_eq!(*test_tags, tags_toml_value(vec![]));
+ }
+
+}
+
diff --git a/libimagentrytag/src/lib.rs b/libimagentrytag/src/lib.rs
index 6cac9690..bfc4d461 100644
--- a/libimagentrytag/src/lib.rs
+++ b/libimagentrytag/src/lib.rs
@@ -48,6 +48,5 @@ pub mod exec;
pub mod result;
pub mod tag;
pub mod tagable;
-pub mod util;
pub mod ui;
diff --git a/libimagentrytag/src/tag.rs b/libimagentrytag/src/tag.rs
index 6cfcf1c8..be968da7 100644
--- a/libimagentrytag/src/tag.rs
+++ b/libimagentrytag/src/tag.rs
@@ -17,6 +17,8 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
+use regex::Regex;
+
pub type Tag = String;
pub type TagSlice<'a> = &'a str;
@@ -31,8 +33,9 @@ pub fn is_tag_str(s: &String) -> Result<(), String> {
let is_lower = |s: &String| s.chars().all(|c| c.is_lowercase());
let no_whitespace = |s: &String| s.chars().all(|c| !c.is_whitespace());
let is_alphanum = |s: &String| s.chars().all(|c| c.is_alphanumeric());
+ let matches_regex = |s: &String| Regex::new("^[a-zA-Z]([a-zA-Z0-9_-]*)$").unwrap().captures(s).is_some();
- if is_lower.and(no_whitespace).and(is_alphanum).filter(s) {
+ if is_lower.and(no_whitespace).and(is_alphanum).and(matches_regex).filter(s) {
Ok(())
} else {
Err(format!("The string '{}' is not a valid tag", s))
diff --git a/libimagentrytag/src/tagable.rs b/libimagentrytag/src/tagable.rs
index 9e0fa2fd..bd53a122 100644
--- a/libimagentrytag/src/tagable.rs
+++ b/libimagentrytag/src/tagable.rs
@@ -27,7 +27,7 @@ use error::TagErrorKind;
use error::MapErrInto;
use result::Result;
use tag::{Tag, TagSlice};
-use util::is_tag;
+use tag::is_tag_str;
use toml::Value;
@@ -55,7 +55,7 @@ impl Tagable for Value {
return Err(TagErrorKind::TagTypeError.into());
}
if tags.iter().any(|t| match *t {
- Value::String(ref s) => !is_tag(s),
+ Value::String(ref s) => !is_tag_str(s).is_ok(),
_ => unreachable!()})
{
return Err(TagErrorKind::NotATag.into());
@@ -77,8 +77,8 @@ impl Tagable for Value {
}
fn set_tags(&mut self, ts: &[Tag]) -> Result<()> {
- if ts.iter().any(|tag| !is_tag(tag)) {
- debug!("Not a tag: '{}'", ts.iter().filter(|t| !is_tag(t)).next().unwrap());
+ if ts.iter().any(|tag| !is_tag_str(tag).is_ok()) {
+ debug!("Not a tag: '{}'", ts.iter().filter(|t| !is_tag_str(t).is_ok()).next().unwrap());
return Err(TagErrorKind::NotATag.into());
}
@@ -90,7 +90,7 @@ impl Tagable for Value {
}
fn add_tag(&mut self, t: Tag) -> Result<()> {
- if !is_tag(&t) {
+ if !try!(is_tag_str(&t).map(|_| true).map_err(|_| TagErrorKind::NotATag.into_error())) {
debug!("Not a tag: '{}'", t);
return Err(TagErrorKind::NotATag.into());
}
@@ -104,7 +104,7 @@ impl Tagable for Value {
}
fn remove_tag(&mut self, t: Tag) -> Result<()> {
- if !is_tag(&t) {
+ if !try!(is_tag_str(&t).map(|_| true).map_err(|_| TagErrorKind::NotATag.into_error())) {
debug!("Not a tag: '{}'", t);
return Err(TagErrorKind::NotATag.into());
}
diff --git a/libimagentrytag/src/ui.rs b/libimagentrytag/src/ui.rs
index dad4c87e..734708b3 100644
--- a/libimagentrytag/src/ui.rs
+++ b/libimagentrytag/src/ui.rs
@@ -20,8 +20,7 @@
use clap::{Arg, ArgMatches, App, SubCommand};
use tag::Tag;
-
-use libimagutil::cli_validators::is_tag;
+use tag::is_tag;
/// Generates a `clap::SubCommand` to be integrated in the commandline-ui builder for building a
/// "tags --add foo --remove bar" subcommand to do tagging action.
diff --git a/libimagentrytag/src/util.rs b/libimagentrytag/src/util.rs
deleted file mode 100644
index d0d31db2..00000000
--- a/libimagentrytag/src/util.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// imag - the personal information management suite for the commandline
-// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> 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
-//
-
-use regex::Regex;
-
-pub fn is_tag(s: &str) -> bool {
- Regex::new("^[a-zA-Z]([a-zA-Z0-9_-]*)$").unwrap().captures(s).is_some()
-}
diff --git a/libimagutil/src/cli_validators.rs b/libimagutil/src/cli_validators.rs
index bbd376f2..24340a4d 100644
--- a/libimagutil/src/cli_validators.rs
+++ b/libimagutil/src/cli_validators.rs
@@ -47,12 +47,3 @@ pub fn is_url(s: String) -> Result<(), String> {
Url::parse(&s).map(|_| ()).map_err(|_| format!("Not a URL: {}", s))
}
-pub fn is_tag(s: String) -> Result<(), String> {
- use regex::Regex;
- lazy_static! { static ref TAG_RE : Regex = Regex::new("[:alpha:][:word:]*").unwrap(); }
-
- TAG_RE
- .is_match(&s)
- .as_result((), format!("Not a valid Tag: '{}' - Valid is [a-zA-Z][0-9a-zA-Z]*", s))
-}
-