diff --git a/src/find/main.rs b/src/find/main.rs index 17a1ea0..1b6b324 100644 --- a/src/find/main.rs +++ b/src/find/main.rs @@ -4,8 +4,8 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. -extern crate glob; extern crate findutils; +extern crate glob; fn main() { let args = std::env::args().collect::>(); diff --git a/src/find/matchers/exec.rs b/src/find/matchers/exec.rs index 87b7bf7..8cf9315 100644 --- a/src/find/matchers/exec.rs +++ b/src/find/matchers/exec.rs @@ -6,7 +6,7 @@ use std::error::Error; use std::ffi::OsString; -use std::io::{Write, stderr}; +use std::io::{stderr, Write}; use std::path::Path; use std::process::Command; use walkdir::DirEntry; @@ -25,12 +25,13 @@ pub struct SingleExecMatcher { } impl SingleExecMatcher { - pub fn new(executable: &str, - args: &[&str], - exec_in_parent_dir: bool) - -> Result> { - - let transformed_args = args.iter() + pub fn new( + executable: &str, + args: &[&str], + exec_in_parent_dir: bool, + ) -> Result> { + let transformed_args = args + .iter() .map(|&a| match a { "{}" => Arg::Filename, _ => Arg::LiteralArg(OsString::from(a)), @@ -44,11 +45,16 @@ impl SingleExecMatcher { }) } - pub fn new_box(executable: &str, - args: &[&str], - exec_in_parent_dir: bool) - -> Result, Box> { - Ok(Box::new(SingleExecMatcher::new(executable, args, exec_in_parent_dir)?)) + pub fn new_box( + executable: &str, + args: &[&str], + exec_in_parent_dir: bool, + ) -> Result, Box> { + Ok(Box::new(SingleExecMatcher::new( + executable, + args, + exec_in_parent_dir, + )?)) } } @@ -72,7 +78,6 @@ impl Matcher for SingleExecMatcher { }); } if self.exec_in_parent_dir { - if file_info.path() == Path::new(".") { command.current_dir(file_info.path()); } else if let Some(parent) = file_info.path().parent() { @@ -93,7 +98,6 @@ impl Matcher for SingleExecMatcher { } } - #[cfg(test)] /// No tests here, because we need to call out to an external executable. See /// tests/exec_unit_tests.rs instead. diff --git a/src/find/matchers/logical_matchers.rs b/src/find/matchers/logical_matchers.rs index c362f96..ceaf698 100644 --- a/src/find/matchers/logical_matchers.rs +++ b/src/find/matchers/logical_matchers.rs @@ -26,17 +26,20 @@ pub struct AndMatcher { impl AndMatcher { pub fn new(submatchers: Vec>) -> AndMatcher { - AndMatcher { submatchers: submatchers } + AndMatcher { + submatchers: submatchers, + } } } - impl Matcher for AndMatcher { /// Returns true if all sub-matchers return true. Short-circuiting does take /// place. If the nth sub-matcher returns false, then we immediately return /// and don't make any further calls. fn matches(&self, dir_entry: &DirEntry, matcher_io: &mut MatcherIO) -> bool { - self.submatchers.iter().all(|x| x.matches(dir_entry, matcher_io)) + self.submatchers + .iter() + .all(|x| x.matches(dir_entry, matcher_io)) } fn has_side_effects(&self) -> bool { @@ -62,7 +65,9 @@ pub struct AndMatcherBuilder { impl AndMatcherBuilder { pub fn new() -> AndMatcherBuilder { - AndMatcherBuilder { submatchers: Vec::new() } + AndMatcherBuilder { + submatchers: Vec::new(), + } } pub fn new_and_condition(&mut self, matcher: Box) { @@ -82,8 +87,6 @@ impl AndMatcherBuilder { } } - - /// This matcher contains a collection of other matchers. A file matches /// if it matches any of the contained sub-matchers. For sub-matchers that have /// side effects, the side effects occur in the same order as the sub-matchers @@ -94,17 +97,20 @@ pub struct OrMatcher { impl OrMatcher { pub fn new(submatchers: Vec>) -> OrMatcher { - OrMatcher { submatchers: submatchers } + OrMatcher { + submatchers: submatchers, + } } } - impl Matcher for OrMatcher { /// Returns true if any sub-matcher returns true. Short-circuiting does take /// place. If the nth sub-matcher returns true, then we immediately return /// and don't make any further calls. fn matches(&self, dir_entry: &DirEntry, matcher_io: &mut MatcherIO) -> bool { - self.submatchers.iter().any(|x| x.matches(dir_entry, matcher_io)) + self.submatchers + .iter() + .any(|x| x.matches(dir_entry, matcher_io)) } fn has_side_effects(&self) -> bool { @@ -131,21 +137,28 @@ pub struct OrMatcherBuilder { impl OrMatcherBuilder { pub fn new_and_condition(&mut self, matcher: Box) { // safe to unwrap. submatchers always has at least one member - self.submatchers.last_mut().unwrap().new_and_condition(matcher); + self.submatchers + .last_mut() + .unwrap() + .new_and_condition(matcher); } pub fn new_or_condition(&mut self, arg: &str) -> Result<(), Box> { if self.submatchers.last().unwrap().submatchers.is_empty() { - return Err(From::from(format!("invalid expression; you have used a binary operator \ - '{}' with nothing before it.", - arg))); + return Err(From::from(format!( + "invalid expression; you have used a binary operator \ + '{}' with nothing before it.", + arg + ))); } self.submatchers.push(AndMatcherBuilder::new()); Ok(()) } pub fn new() -> OrMatcherBuilder { - let mut o = OrMatcherBuilder { submatchers: Vec::new() }; + let mut o = OrMatcherBuilder { + submatchers: Vec::new(), + }; o.submatchers.push(AndMatcherBuilder::new()); o } @@ -165,7 +178,6 @@ impl OrMatcherBuilder { } } - /// This matcher contains a collection of other matchers. In contrast to /// `OrMatcher` and `AndMatcher`, all the submatcher objects are called /// regardless of the results of previous submatchers. This is primarily used @@ -177,11 +189,12 @@ pub struct ListMatcher { impl ListMatcher { pub fn new(submatchers: Vec>) -> ListMatcher { - ListMatcher { submatchers: submatchers } + ListMatcher { + submatchers: submatchers, + } } } - impl Matcher for ListMatcher { /// Calls matches on all submatcher objects, with no short-circuiting. /// Returns the result of the call to the final submatcher @@ -217,7 +230,10 @@ pub struct ListMatcherBuilder { impl ListMatcherBuilder { pub fn new_and_condition(&mut self, matcher: Box) { // safe to unwrap. submatchers always has at least one member - self.submatchers.last_mut().unwrap().new_and_condition(matcher); + self.submatchers + .last_mut() + .unwrap() + .new_and_condition(matcher); } pub fn new_or_condition(&mut self, arg: &str) -> Result<(), Box> { @@ -230,8 +246,10 @@ impl ListMatcherBuilder { let grandchild_and_matcher = &child_or_matcher.submatchers.last().unwrap(); if grandchild_and_matcher.submatchers.is_empty() { - return Err(From::from("invalid expression; you have used a binary operator '-a' \ - with nothing before it.")); + return Err(From::from( + "invalid expression; you have used a binary operator '-a' \ + with nothing before it.", + )); } } Ok(()) @@ -243,8 +261,10 @@ impl ListMatcherBuilder { let grandchild_and_matcher = &child_or_matcher.submatchers.last().unwrap(); if grandchild_and_matcher.submatchers.is_empty() { - return Err(From::from("invalid expression; you have used a binary operator ',' \ - with nothing before it.")); + return Err(From::from( + "invalid expression; you have used a binary operator ',' \ + with nothing before it.", + )); } } self.submatchers.push(OrMatcherBuilder::new()); @@ -252,7 +272,9 @@ impl ListMatcherBuilder { } pub fn new() -> ListMatcherBuilder { - let mut o = ListMatcherBuilder { submatchers: Vec::new() }; + let mut o = ListMatcherBuilder { + submatchers: Vec::new(), + }; o.submatchers.push(OrMatcherBuilder::new()); o } @@ -272,7 +294,6 @@ impl ListMatcherBuilder { } } - /// A simple matcher that always matches. pub struct TrueMatcher; @@ -303,7 +324,6 @@ impl FalseMatcher { } } - /// Matcher that wraps another matcher and inverts matching criteria. pub struct NotMatcher { submatcher: Box, @@ -311,7 +331,9 @@ pub struct NotMatcher { impl NotMatcher { pub fn new(submatcher: Box) -> NotMatcher { - NotMatcher { submatcher: submatcher } + NotMatcher { + submatcher: submatcher, + } } pub fn new_box(submatcher: Box) -> Box { @@ -340,11 +362,11 @@ impl Matcher for NotMatcher { #[cfg(test)] mod tests { - use walkdir::DirEntry; - use crate::find::matchers::tests::get_dir_entry_for; use super::*; + use crate::find::matchers::tests::get_dir_entry_for; use crate::find::matchers::{Matcher, MatcherIO}; use crate::find::tests::FakeDependencies; + use walkdir::DirEntry; /// Simple Matcher impl that has side effects pub struct HasSideEffects {} @@ -365,8 +387,6 @@ mod tests { } } - - #[test] fn and_matches_works() { let abbbc = get_dir_entry_for("test_data/simple", "abbbc"); diff --git a/src/find/matchers/mod.rs b/src/find/matchers/mod.rs index e924f63..042b6c3 100644 --- a/src/find/matchers/mod.rs +++ b/src/find/matchers/mod.rs @@ -22,8 +22,6 @@ use walkdir::DirEntry; use super::{Config, Dependencies}; - - /// Struct holding references to outputs and any inputs that can't be derived /// from the file/directory info. pub struct MatcherIO<'a> { @@ -89,8 +87,8 @@ impl ComparableValue { fn matches(&self, value: u64) -> bool { match *self { ComparableValue::MoreThan(limit) => value > limit, - ComparableValue::EqualTo(limit) => value == limit, - ComparableValue::LessThan(limit) => value < limit, + ComparableValue::EqualTo(limit) => value == limit, + ComparableValue::LessThan(limit) => value < limit, } } @@ -98,18 +96,18 @@ impl ComparableValue { fn imatches(&self, value: i64) -> bool { match *self { ComparableValue::MoreThan(limit) => value >= 0 && (value as u64) > limit, - ComparableValue::EqualTo(limit) => value >= 0 && (value as u64) == limit, - ComparableValue::LessThan(limit) => value < 0 || (value as u64) < limit, + ComparableValue::EqualTo(limit) => value >= 0 && (value as u64) == limit, + ComparableValue::LessThan(limit) => value < 0 || (value as u64) < limit, } } } - /// Builds a single `AndMatcher` containing the Matcher objects corresponding /// to the passed in predicate arguments. -pub fn build_top_level_matcher(args: &[&str], - config: &mut Config) - -> Result, Box> { +pub fn build_top_level_matcher( + args: &[&str], + config: &mut Config, +) -> Result, Box> { let (_, top_level_matcher) = (build_matcher_tree(args, config, 0, false))?; // if the matcher doesn't have any side-effects, then we default to printing @@ -130,18 +128,18 @@ fn are_more_expressions(args: &[&str], index: usize) -> bool { fn convert_arg_to_number(option_name: &str, value_as_string: &str) -> Result> { match value_as_string.parse::() { Ok(val) => Ok(val), - _ => { - Err(From::from(format!("Expected a positive decimal integer argument to {}, but got \ - `{}'", - option_name, - value_as_string))) - } + _ => Err(From::from(format!( + "Expected a positive decimal integer argument to {}, but got \ + `{}'", + option_name, value_as_string + ))), } } -fn convert_arg_to_comparable_value(option_name: &str, - value_as_string: &str) - -> Result> { +fn convert_arg_to_comparable_value( + option_name: &str, + value_as_string: &str, +) -> Result> { let re = Regex::new(r"([+-]?)(\d+)$")?; if let Some(groups) = re.captures(value_as_string) { if let Ok(val) = groups[2].parse::() { @@ -152,42 +150,47 @@ fn convert_arg_to_comparable_value(option_name: &str, }); } } - Err(From::from(format!("Expected a decimal integer (with optional + or - prefix) argument \ - to {}, but got `{}'", - option_name, - value_as_string))) + Err(From::from(format!( + "Expected a decimal integer (with optional + or - prefix) argument \ + to {}, but got `{}'", + option_name, value_as_string + ))) } -fn convert_arg_to_comparable_value_and_suffix(option_name: &str, - value_as_string: &str) - -> Result<(ComparableValue, String), Box> { +fn convert_arg_to_comparable_value_and_suffix( + option_name: &str, + value_as_string: &str, +) -> Result<(ComparableValue, String), Box> { let re = Regex::new(r"([+-]?)(\d+)(.*)$")?; if let Some(groups) = re.captures(value_as_string) { if let Ok(val) = groups[2].parse::() { - return Ok((match &groups[1] { - "+" => ComparableValue::MoreThan(val), - "-" => ComparableValue::LessThan(val), - _ => ComparableValue::EqualTo(val), - }, - groups[3].to_string())); + return Ok(( + match &groups[1] { + "+" => ComparableValue::MoreThan(val), + "-" => ComparableValue::LessThan(val), + _ => ComparableValue::EqualTo(val), + }, + groups[3].to_string(), + )); } } - Err(From::from(format!("Expected a decimal integer (with optional + or - prefix) and \ - (optional suffix) argument to {}, but got `{}'", - option_name, - value_as_string))) + Err(From::from(format!( + "Expected a decimal integer (with optional + or - prefix) and \ + (optional suffix) argument to {}, but got `{}'", + option_name, value_as_string + ))) } - /// The main "translate command-line args into a matcher" function. Will call /// itself recursively if it encounters an opening bracket. A successful return /// consits of a tuple containing the new index into the args array to use (if /// called recursively) and the resulting matcher. -fn build_matcher_tree(args: &[&str], - config: &mut Config, - arg_index: usize, - expecting_bracket: bool) - -> Result<(usize, Box), Box> { +fn build_matcher_tree( + args: &[&str], + config: &mut Config, + arg_index: usize, + expecting_bracket: bool, +) -> Result<(usize, Box), Box> { let mut top_level_matcher = logical_matchers::ListMatcherBuilder::new(); // can't use getopts for a variety or reasons: @@ -249,8 +252,8 @@ fn build_matcher_tree(args: &[&str], if i >= args.len() - 1 { return Err(From::from(format!("missing argument to {}", args[i]))); } - let (size, unit) = convert_arg_to_comparable_value_and_suffix(args[i], - args[i + 1])?; + let (size, unit) = + convert_arg_to_comparable_value_and_suffix(args[i], args[i + 1])?; i += 1; Some(size::SizeMatcher::new_box(size, &unit)?) } @@ -259,10 +262,11 @@ fn build_matcher_tree(args: &[&str], while arg_index < args.len() && args[arg_index] != ";" { if args[arg_index] == "+" { // MultiExecMatcher isn't written yet - return Err(From::from(format!("{} [args...] + isn't supported yet. \ - Only {} [args...] ;", - args[i], - args[i]))); + return Err(From::from(format!( + "{} [args...] + isn't supported yet. \ + Only {} [args...] ;", + args[i], args[i] + ))); } arg_index += 1; } @@ -274,9 +278,11 @@ fn build_matcher_tree(args: &[&str], let executable = args[i + 1]; let exec_args = &args[i + 2..arg_index]; i = arg_index; - Some(exec::SingleExecMatcher::new_box(executable, - exec_args, - expression == "-execdir")?) + Some(exec::SingleExecMatcher::new_box( + executable, + exec_args, + expression == "-execdir", + )?) } "-perm" => { if i >= args.len() - 1 { @@ -288,28 +294,40 @@ fn build_matcher_tree(args: &[&str], "-prune" => Some(prune::PruneMatcher::new_box()), "-not" | "!" => { if !are_more_expressions(args, i) { - return Err(From::from(format!("expected an expression after {}", args[i]))); + return Err(From::from(format!( + "expected an expression after {}", + args[i] + ))); } invert_next_matcher = !invert_next_matcher; None } "-a" => { if !are_more_expressions(args, i) { - return Err(From::from(format!("expected an expression after {}", args[i]))); + return Err(From::from(format!( + "expected an expression after {}", + args[i] + ))); } top_level_matcher.check_new_and_condition()?; None } "-or" | "-o" => { if !are_more_expressions(args, i) { - return Err(From::from(format!("expected an expression after {}", args[i]))); + return Err(From::from(format!( + "expected an expression after {}", + args[i] + ))); } top_level_matcher.new_or_condition(args[i])?; None } "," => { if !are_more_expressions(args, i) { - return Err(From::from(format!("expected an expression after {}", args[i]))); + return Err(From::from(format!( + "expected an expression after {}", + args[i] + ))); } top_level_matcher.new_list_condition()?; None @@ -360,7 +378,8 @@ fn build_matcher_tree(args: &[&str], }; if let Some(submatcher) = possible_submatcher { if invert_next_matcher { - top_level_matcher.new_and_condition(logical_matchers::NotMatcher::new_box(submatcher)); + top_level_matcher + .new_and_condition(logical_matchers::NotMatcher::new_box(submatcher)); invert_next_matcher = false; } else { top_level_matcher.new_and_condition(submatcher); @@ -369,21 +388,21 @@ fn build_matcher_tree(args: &[&str], i += 1; } if expecting_bracket { - return Err(From::from("invalid expression; I was expecting to find a ')' somewhere but \ - did not see one.")); + return Err(From::from( + "invalid expression; I was expecting to find a ')' somewhere but \ + did not see one.", + )); } Ok((i, top_level_matcher.build())) } #[cfg(test)] mod tests { - use walkdir::{DirEntry, WalkDir}; - use crate::find::Config; + use super::*; use crate::find::tests::fix_up_slashes; use crate::find::tests::FakeDependencies; - use super::*; - - + use crate::find::Config; + use walkdir::{DirEntry, WalkDir}; /// Helper function for tests to get a DirEntry object. directory should /// probably be a string starting with "test_data/" (cargo's tests run with @@ -409,8 +428,10 @@ mod tests { assert!(matcher.matches(&abbbc_lower, &mut deps.new_matcher_io())); assert!(!matcher.matches(&abbbc_upper, &mut deps.new_matcher_io())); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple/abbbc\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/simple/abbbc\n") + ); } #[test] @@ -424,8 +445,10 @@ mod tests { assert!(matcher.matches(&abbbc_lower, &mut deps.new_matcher_io())); assert!(matcher.matches(&abbbc_upper, &mut deps.new_matcher_io())); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple/abbbc\n./test_data/simple/subdir/ABBBC\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/simple/abbbc\n./test_data/simple/subdir/ABBBC\n") + ); } #[test] @@ -435,12 +458,14 @@ mod tests { let mut config = Config::default(); let deps = FakeDependencies::new(); - let matcher = build_top_level_matcher(&[arg, "-name", "doesntexist"], &mut config) - .unwrap(); + let matcher = + build_top_level_matcher(&[arg, "-name", "doesntexist"], &mut config).unwrap(); assert!(matcher.matches(&abbbc_lower, &mut deps.new_matcher_io())); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple/abbbc\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/simple/abbbc\n") + ); } } @@ -464,16 +489,18 @@ mod tests { let mut config = Config::default(); let deps = FakeDependencies::new(); - let matcher = build_top_level_matcher(&[arg, arg, "-name", "abbbc"], &mut config) - .unwrap(); + let matcher = + build_top_level_matcher(&[arg, arg, "-name", "abbbc"], &mut config).unwrap(); assert!(matcher.matches(&abbbc_lower, &mut deps.new_matcher_io())); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple/abbbc\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/simple/abbbc\n") + ); config = Config::default(); - let matcher = build_top_level_matcher(&[arg, arg, "-name", "doesntexist"], &mut config) - .unwrap(); + let matcher = + build_top_level_matcher(&[arg, arg, "-name", "doesntexist"], &mut config).unwrap(); assert!(!matcher.matches(&abbbc_lower, &mut deps.new_matcher_io())); } @@ -550,24 +577,30 @@ mod tests { // build a matcher using an explicit -a argument let matcher = build_top_level_matcher(&["-true", "-a", "-true"], &mut config).unwrap(); assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io())); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple/abbbc\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/simple/abbbc\n") + ); } #[test] fn build_top_level_matcher_or_works() { let abbbc = get_dir_entry_for("./test_data/simple", "abbbc"); - for args in &[["-true", "-o", "-false"], - ["-false", "-o", "-true"], - ["-true", "-o", "-true"]] { + for args in &[ + ["-true", "-o", "-false"], + ["-false", "-o", "-true"], + ["-true", "-o", "-true"], + ] { let mut config = Config::default(); let deps = FakeDependencies::new(); let matcher = build_top_level_matcher(args, &mut config).unwrap(); assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io())); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple/abbbc\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/simple/abbbc\n") + ); } let mut config = Config::default(); @@ -582,7 +615,11 @@ mod tests { #[test] fn build_top_level_matcher_and_works() { let abbbc = get_dir_entry_for("./test_data/simple", "abbbc"); - for args in &[["-true", "-false"], ["-false", "-true"], ["-false", "-false"]] { + for args in &[ + ["-true", "-false"], + ["-false", "-true"], + ["-false", "-false"], + ] { let mut config = Config::default(); let deps = FakeDependencies::new(); @@ -598,8 +635,10 @@ mod tests { let matcher = build_top_level_matcher(&["-true", "-true"], &mut config).unwrap(); assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io())); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple/abbbc\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/simple/abbbc\n") + ); } #[test] @@ -614,8 +653,10 @@ mod tests { // final matcher returns false, so list matcher should too assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io())); // two print matchers means doubled output - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple/abbbc\n./test_data/simple/abbbc\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/simple/abbbc\n./test_data/simple/abbbc\n") + ); } #[test] @@ -719,78 +760,138 @@ mod tests { #[test] fn comparable_value_matches() { + assert!( + !ComparableValue::LessThan(0).matches(0), + "0 should not be less than 0" + ); + assert!( + ComparableValue::LessThan(u64::max_value()).matches(0), + "0 should be less than max_value" + ); + assert!( + !ComparableValue::LessThan(0).matches(u64::max_value()), + "max_value should not be less than 0" + ); + assert!( + !ComparableValue::LessThan(u64::max_value()).matches(u64::max_value()), + "max_value should not be less than max_value" + ); - assert!(!ComparableValue::LessThan(0).matches(0), - "0 should not be less than 0"); - assert!(ComparableValue::LessThan(u64::max_value()).matches(0), - "0 should be less than max_value"); - assert!(!ComparableValue::LessThan(0).matches(u64::max_value()), - "max_value should not be less than 0"); - assert!(!ComparableValue::LessThan(u64::max_value()).matches(u64::max_value()), - "max_value should not be less than max_value"); + assert!( + ComparableValue::EqualTo(0).matches(0), + "0 should be equal to 0" + ); + assert!( + !ComparableValue::EqualTo(u64::max_value()).matches(0), + "0 should not be equal to max_value" + ); + assert!( + !ComparableValue::EqualTo(0).matches(u64::max_value()), + "max_value should not be equal to 0" + ); + assert!( + ComparableValue::EqualTo(u64::max_value()).matches(u64::max_value()), + "max_value should be equal to max_value" + ); - assert!(ComparableValue::EqualTo(0).matches(0), - "0 should be equal to 0"); - assert!(!ComparableValue::EqualTo(u64::max_value()).matches(0), - "0 should not be equal to max_value"); - assert!(!ComparableValue::EqualTo(0).matches(u64::max_value()), - "max_value should not be equal to 0"); - assert!(ComparableValue::EqualTo(u64::max_value()).matches(u64::max_value()), - "max_value should be equal to max_value"); - - assert!(!ComparableValue::MoreThan(0).matches(0), - "0 should not be more than 0"); - assert!(!ComparableValue::MoreThan(u64::max_value()).matches(0), - "0 should not be more than max_value"); - assert!(ComparableValue::MoreThan(0).matches(u64::max_value()), - "max_value should be more than 0"); - assert!(!ComparableValue::MoreThan(u64::max_value()).matches(u64::max_value()), - "max_value should not be more than max_value"); + assert!( + !ComparableValue::MoreThan(0).matches(0), + "0 should not be more than 0" + ); + assert!( + !ComparableValue::MoreThan(u64::max_value()).matches(0), + "0 should not be more than max_value" + ); + assert!( + ComparableValue::MoreThan(0).matches(u64::max_value()), + "max_value should be more than 0" + ); + assert!( + !ComparableValue::MoreThan(u64::max_value()).matches(u64::max_value()), + "max_value should not be more than max_value" + ); } #[test] fn comparable_value_imatches() { + assert!( + !ComparableValue::LessThan(0).imatches(0), + "0 should not be less than 0" + ); + assert!( + ComparableValue::LessThan(u64::max_value()).imatches(0), + "0 should be less than max_value" + ); + assert!( + !ComparableValue::LessThan(0).imatches(i64::max_value()), + "max_value should not be less than 0" + ); + assert!( + ComparableValue::LessThan(u64::max_value()).imatches(i64::max_value()), + "max_value should be less than max_value" + ); + assert!( + ComparableValue::LessThan(0).imatches(i64::min_value()), + "min_value should be less than 0" + ); + assert!( + ComparableValue::LessThan(u64::max_value()).imatches(i64::min_value()), + "min_value should be less than max_value" + ); - assert!(!ComparableValue::LessThan(0).imatches(0), - "0 should not be less than 0"); - assert!(ComparableValue::LessThan(u64::max_value()).imatches(0), - "0 should be less than max_value"); - assert!(!ComparableValue::LessThan(0).imatches(i64::max_value()), - "max_value should not be less than 0"); - assert!(ComparableValue::LessThan(u64::max_value()).imatches(i64::max_value()), - "max_value should be less than max_value"); - assert!(ComparableValue::LessThan(0).imatches(i64::min_value()), - "min_value should be less than 0"); - assert!(ComparableValue::LessThan(u64::max_value()).imatches(i64::min_value()), - "min_value should be less than max_value"); + assert!( + ComparableValue::EqualTo(0).imatches(0), + "0 should be equal to 0" + ); + assert!( + !ComparableValue::EqualTo(u64::max_value()).imatches(0), + "0 should not be equal to max_value" + ); + assert!( + !ComparableValue::EqualTo(0).imatches(i64::max_value()), + "max_value should not be equal to 0" + ); + assert!( + !ComparableValue::EqualTo(u64::max_value()).imatches(i64::max_value()), + "max_value should not be equal to i64::max_value" + ); + assert!( + ComparableValue::EqualTo(i64::max_value() as u64).imatches(i64::max_value()), + "i64::max_value should be equal to i64::max_value" + ); + assert!( + !ComparableValue::EqualTo(0).imatches(i64::min_value()), + "min_value should not be equal to 0" + ); + assert!( + !ComparableValue::EqualTo(u64::max_value()).imatches(i64::min_value()), + "min_value should not be equal to max_value" + ); - assert!(ComparableValue::EqualTo(0).imatches(0), - "0 should be equal to 0"); - assert!(!ComparableValue::EqualTo(u64::max_value()).imatches(0), - "0 should not be equal to max_value"); - assert!(!ComparableValue::EqualTo(0).imatches(i64::max_value()), - "max_value should not be equal to 0"); - assert!(!ComparableValue::EqualTo(u64::max_value()).imatches(i64::max_value()), - "max_value should not be equal to i64::max_value"); - assert!(ComparableValue::EqualTo(i64::max_value() as u64).imatches(i64::max_value()), - "i64::max_value should be equal to i64::max_value"); - assert!(!ComparableValue::EqualTo(0).imatches(i64::min_value()), - "min_value should not be equal to 0"); - assert!(!ComparableValue::EqualTo(u64::max_value()).imatches(i64::min_value()), - "min_value should not be equal to max_value"); - - assert!(!ComparableValue::MoreThan(0).imatches(0), - "0 should not be more than 0"); - assert!(!ComparableValue::MoreThan(u64::max_value()).imatches(0), - "0 should not be more than max_value"); - assert!(ComparableValue::MoreThan(0).imatches(i64::max_value()), - "max_value should be more than 0"); - assert!(!ComparableValue::MoreThan(u64::max_value()).imatches(i64::max_value()), - "max_value should not be more than max_value"); - assert!(!ComparableValue::MoreThan(0).imatches(i64::min_value()), - "min_value should not be more than 0"); - assert!(!ComparableValue::MoreThan(u64::max_value()).imatches(i64::min_value()), - "min_value should not be more than max_value"); + assert!( + !ComparableValue::MoreThan(0).imatches(0), + "0 should not be more than 0" + ); + assert!( + !ComparableValue::MoreThan(u64::max_value()).imatches(0), + "0 should not be more than max_value" + ); + assert!( + ComparableValue::MoreThan(0).imatches(i64::max_value()), + "max_value should be more than 0" + ); + assert!( + !ComparableValue::MoreThan(u64::max_value()).imatches(i64::max_value()), + "max_value should not be more than max_value" + ); + assert!( + !ComparableValue::MoreThan(0).imatches(i64::min_value()), + "min_value should not be more than 0" + ); + assert!( + !ComparableValue::MoreThan(u64::max_value()).imatches(i64::min_value()), + "min_value should not be more than max_value" + ); } #[test] @@ -798,9 +899,11 @@ mod tests { let mut config = Config::default(); if let Err(e) = build_top_level_matcher(&["-ctime", "-123."], &mut config) { - assert!(e.description().contains("Expected a decimal integer"), - "bad description: {}", - e); + assert!( + e.description().contains("Expected a decimal integer"), + "bad description: {}", + e + ); } else { panic!("parsing a bad ctime value should fail"); } diff --git a/src/find/matchers/name.rs b/src/find/matchers/name.rs index 795901b..2b3395e 100644 --- a/src/find/matchers/name.rs +++ b/src/find/matchers/name.rs @@ -30,7 +30,8 @@ impl NameMatcher { impl Matcher for NameMatcher { fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool { - self.pattern.matches(file_info.file_name().to_string_lossy().as_ref()) + self.pattern + .matches(file_info.file_name().to_string_lossy().as_ref()) } } @@ -54,20 +55,23 @@ impl CaselessNameMatcher { impl super::Matcher for CaselessNameMatcher { fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool { - self.pattern - .matches(file_info.file_name().to_string_lossy().to_lowercase().as_ref()) + self.pattern.matches( + file_info + .file_name() + .to_string_lossy() + .to_lowercase() + .as_ref(), + ) } } - #[cfg(test)] mod tests { - use crate::find::matchers::Matcher; - use crate::find::matchers::tests::get_dir_entry_for; - use crate::find::tests::FakeDependencies; use super::*; - + use crate::find::matchers::tests::get_dir_entry_for; + use crate::find::matchers::Matcher; + use crate::find::tests::FakeDependencies; #[test] fn matching_with_wrong_case_returns_false() { diff --git a/src/find/matchers/perm.rs b/src/find/matchers/perm.rs index 5d0ca76..a8ebde4 100644 --- a/src/find/matchers/perm.rs +++ b/src/find/matchers/perm.rs @@ -16,7 +16,6 @@ use walkdir::DirEntry; use super::{Matcher, MatcherIO}; - #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[cfg(unix)] pub enum ComparisonType { @@ -38,9 +37,11 @@ impl FromStr for ComparisonType { "-" => ComparisonType::AtLeast, "/" => ComparisonType::AnyOf, _ => { - return Err(From::from(format!("Invalid prefix {} for -perm. Only allowed \ - values are , /, or -", - s))); + return Err(From::from(format!( + "Invalid prefix {} for -perm. Only allowed \ + values are , /, or -", + s + ))); } }) } @@ -59,9 +60,9 @@ impl ComparisonType { #[cfg(unix)] mod parsing { + use super::*; use regex::Regex; use std::error::Error; - use super::*; // We need to be able to parse strings like /u+rw,g+w,o=w. Specifically // we have a prefix, as per ComparisonType. then combinations of (u, g or o @@ -69,8 +70,8 @@ mod parsing { // commas. Writing a hard-coded parser is easier to understand - and probably // shorter :-) - than the abomination required to do this as a regex enum ParserState { - Beginning, // we're at the start, now waiting for /, -, a, u, g or o - GatheringCategories, // expecting u, g or o to set categories, or =/+ to switch to... + Beginning, // we're at the start, now waiting for /, -, a, u, g or o + GatheringCategories, // expecting u, g or o to set categories, or =/+ to switch to... GatheringPermissions, // expecting r, w, or x } @@ -82,7 +83,6 @@ mod parsing { category_bit_pattern: u32, } - impl<'a> Parser<'a> { fn new(string_pattern: &'a str) -> Parser<'a> { Parser { @@ -95,13 +95,15 @@ mod parsing { } fn error(&self) -> Result<(), Box> { - Err(From::from(format!("invalid mode '{}'", self.string_pattern))) + Err(From::from(format!( + "invalid mode '{}'", + self.string_pattern + ))) } fn handle_char(&mut self, char: &char) -> Result<(), Box> { if let ParserState::Beginning = self.state {}; - match *char { '-' => { if let ParserState::Beginning = self.state { @@ -121,8 +123,7 @@ mod parsing { } 'a' => { match self.state { - ParserState::Beginning | - ParserState::GatheringCategories => { + ParserState::Beginning | ParserState::GatheringCategories => { self.state = ParserState::GatheringCategories; self.category_bit_pattern = 0o111; } @@ -133,8 +134,7 @@ mod parsing { } 'g' => { match self.state { - ParserState::Beginning | - ParserState::GatheringCategories => { + ParserState::Beginning | ParserState::GatheringCategories => { self.state = ParserState::GatheringCategories; self.category_bit_pattern |= 0o010; } @@ -145,8 +145,7 @@ mod parsing { } 'u' => { match self.state { - ParserState::Beginning | - ParserState::GatheringCategories => { + ParserState::Beginning | ParserState::GatheringCategories => { self.state = ParserState::GatheringCategories; self.category_bit_pattern |= 0o100; } @@ -157,8 +156,7 @@ mod parsing { } 'o' => { match self.state { - ParserState::Beginning | - ParserState::GatheringCategories => { + ParserState::Beginning | ParserState::GatheringCategories => { self.state = ParserState::GatheringCategories; self.category_bit_pattern |= 0o001; } @@ -244,12 +242,13 @@ mod parsing { return Ok((val, m.get(1).unwrap().as_str().parse().unwrap())); } Err(e) => { - return Err(From::from(format!("Failed to parse -perm argument {}: {}", - m.get(2).unwrap().as_str(), - e))); + return Err(From::from(format!( + "Failed to parse -perm argument {}: {}", + m.get(2).unwrap().as_str(), + e + ))); } } - } // no: so we've got a /u=rw,g=r form instead (or an invalid string). let mut p = Parser::new(string_value); @@ -281,7 +280,9 @@ impl PermMatcher { #[cfg(not(unix))] pub fn new(_dummy_pattern: &str) -> Result> { - Err(From::from("Permission matching is not available on this platform")) + Err(From::from( + "Permission matching is not available on this platform", + )) } pub fn new_box(pattern: &str) -> Result, Box> { @@ -294,15 +295,17 @@ impl Matcher for PermMatcher { fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool { use std::os::unix::fs::PermissionsExt; match file_info.metadata() { - Ok(metadata) => { - self.comparison_type.mode_bits_match(self.pattern, metadata.permissions().mode()) - } + Ok(metadata) => self + .comparison_type + .mode_bits_match(self.pattern, metadata.permissions().mode()), Err(e) => { - writeln!(&mut stderr(), - "Error getting permissions for {}: {}", - file_info.path().to_string_lossy(), - e) - .unwrap(); + writeln!( + &mut stderr(), + "Error getting permissions for {}: {}", + file_info.path().to_string_lossy(), + e + ) + .unwrap(); false } } @@ -310,180 +313,290 @@ impl Matcher for PermMatcher { #[cfg(not(unix))] fn matches(&self, _dummy_file_info: &DirEntry, _: &mut MatcherIO) -> bool { - writeln!(&mut stderr(), - "Permission matching not available on this platform!") - .unwrap(); + writeln!( + &mut stderr(), + "Permission matching not available on this platform!" + ) + .unwrap(); return false; } } - #[cfg(test)] #[cfg(unix)] mod tests { - use crate::find::matchers::Matcher; - use crate::find::matchers::tests::get_dir_entry_for; - use crate::find::tests::FakeDependencies; - use super::*; use super::parsing; + use super::*; + use crate::find::matchers::tests::get_dir_entry_for; + use crate::find::matchers::Matcher; + use crate::find::tests::FakeDependencies; #[test] fn parsing_prefix() { - assert_eq!(parsing::parse("u=rwx").unwrap(), - (0o700, ComparisonType::Exact)); - assert_eq!(parsing::parse("-u=rwx").unwrap(), - (0o700, ComparisonType::AtLeast)); - assert_eq!(parsing::parse("/u=rwx").unwrap(), - (0o700, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("700").unwrap(), - (0o700, ComparisonType::Exact)); - assert_eq!(parsing::parse("-700").unwrap(), - (0o700, ComparisonType::AtLeast)); - assert_eq!(parsing::parse("/700").unwrap(), - (0o700, ComparisonType::AnyOf)); + assert_eq!( + parsing::parse("u=rwx").unwrap(), + (0o700, ComparisonType::Exact) + ); + assert_eq!( + parsing::parse("-u=rwx").unwrap(), + (0o700, ComparisonType::AtLeast) + ); + assert_eq!( + parsing::parse("/u=rwx").unwrap(), + (0o700, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("700").unwrap(), + (0o700, ComparisonType::Exact) + ); + assert_eq!( + parsing::parse("-700").unwrap(), + (0o700, ComparisonType::AtLeast) + ); + assert_eq!( + parsing::parse("/700").unwrap(), + (0o700, ComparisonType::AnyOf) + ); } #[test] fn parsing_octal() { assert_eq!(parsing::parse("/1").unwrap(), (0o1, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/7777").unwrap(), - (0o7777, ComparisonType::AnyOf)); + assert_eq!( + parsing::parse("/7777").unwrap(), + (0o7777, ComparisonType::AnyOf) + ); } #[test] fn parsing_human_readable_individual_bits() { assert_eq!(parsing::parse("/").unwrap(), (0o0, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/u=r").unwrap(), - (0o400, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/u=w").unwrap(), - (0o200, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/u=x").unwrap(), - (0o100, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/g=r").unwrap(), - (0o40, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/g=w").unwrap(), - (0o20, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/g=x").unwrap(), - (0o10, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/o+r").unwrap(), - (0o4, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/o+w").unwrap(), - (0o2, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/o+x").unwrap(), - (0o1, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/a+r").unwrap(), - (0o444, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/a+w").unwrap(), - (0o222, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/a+x").unwrap(), - (0o111, ComparisonType::AnyOf)); + assert_eq!( + parsing::parse("/u=r").unwrap(), + (0o400, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/u=w").unwrap(), + (0o200, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/u=x").unwrap(), + (0o100, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/g=r").unwrap(), + (0o40, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/g=w").unwrap(), + (0o20, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/g=x").unwrap(), + (0o10, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/o+r").unwrap(), + (0o4, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/o+w").unwrap(), + (0o2, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/o+x").unwrap(), + (0o1, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/a+r").unwrap(), + (0o444, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/a+w").unwrap(), + (0o222, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/a+x").unwrap(), + (0o111, ComparisonType::AnyOf) + ); } #[test] fn parsing_human_readable_multiple_bits() { - assert_eq!(parsing::parse("/u=rwx").unwrap(), - (0o700, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/a=rwx").unwrap(), - (0o777, ComparisonType::AnyOf)); + assert_eq!( + parsing::parse("/u=rwx").unwrap(), + (0o700, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/a=rwx").unwrap(), + (0o777, ComparisonType::AnyOf) + ); } #[test] fn parsing_human_readable_multiple_categories() { - assert_eq!(parsing::parse("/u=rwx,g=rx,o+r").unwrap(), - (0o754, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/u=rwx,g=rx,o+r,a+w").unwrap(), - (0o776, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/ug=rwx,o+r").unwrap(), - (0o774, ComparisonType::AnyOf)); + assert_eq!( + parsing::parse("/u=rwx,g=rx,o+r").unwrap(), + (0o754, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/u=rwx,g=rx,o+r,a+w").unwrap(), + (0o776, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/ug=rwx,o+r").unwrap(), + (0o774, ComparisonType::AnyOf) + ); } #[test] fn parsing_human_readable_set_id_bits() { - assert_eq!(parsing::parse("/u=s").unwrap(), - (0o4000, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/g=s").unwrap(), - (0o2000, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/ug=s").unwrap(), - (0o6000, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/o=s").unwrap(), - (0o0000, ComparisonType::AnyOf)); + assert_eq!( + parsing::parse("/u=s").unwrap(), + (0o4000, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/g=s").unwrap(), + (0o2000, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/ug=s").unwrap(), + (0o6000, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/o=s").unwrap(), + (0o0000, ComparisonType::AnyOf) + ); } #[test] fn parsing_human_readable_sticky_bit() { - assert_eq!(parsing::parse("/u=t").unwrap(), - (0o1000, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/g=t").unwrap(), - (0o1000, ComparisonType::AnyOf)); - assert_eq!(parsing::parse("/o=t").unwrap(), - (0o1000, ComparisonType::AnyOf)); + assert_eq!( + parsing::parse("/u=t").unwrap(), + (0o1000, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/g=t").unwrap(), + (0o1000, ComparisonType::AnyOf) + ); + assert_eq!( + parsing::parse("/o=t").unwrap(), + (0o1000, ComparisonType::AnyOf) + ); } - #[test] fn parsing_fails() { - assert!(parsing::parse("+u=rwx,g=rx,o+r").is_err(), - "invalid prefix should fail"); - assert!(parsing::parse("urwx,g=rx,o+r").is_err(), - "missing equals should fail"); - assert!(parsing::parse("d=rwx,g=rx,o+r").is_err(), - "invalid category should fail"); - assert!(parsing::parse("u=dwx,g=rx,o+r").is_err(), - "invalid permission bit should fail"); - assert!(parsing::parse("u=rwxg=rx,o+r").is_err(), - "missing comma should fail"); - assert!(parsing::parse("u_rwx,g=rx,o+r").is_err(), - "invalid category/permissoin spearator should fail"); - assert!(parsing::parse("77777777777777").is_err(), - "overflowing octal value should fail"); + assert!( + parsing::parse("+u=rwx,g=rx,o+r").is_err(), + "invalid prefix should fail" + ); + assert!( + parsing::parse("urwx,g=rx,o+r").is_err(), + "missing equals should fail" + ); + assert!( + parsing::parse("d=rwx,g=rx,o+r").is_err(), + "invalid category should fail" + ); + assert!( + parsing::parse("u=dwx,g=rx,o+r").is_err(), + "invalid permission bit should fail" + ); + assert!( + parsing::parse("u=rwxg=rx,o+r").is_err(), + "missing comma should fail" + ); + assert!( + parsing::parse("u_rwx,g=rx,o+r").is_err(), + "invalid category/permissoin spearator should fail" + ); + assert!( + parsing::parse("77777777777777").is_err(), + "overflowing octal value should fail" + ); } #[test] fn comparison_type_matching() { let c = ComparisonType::Exact; - assert!(c.mode_bits_match(0, 0), - "Exact: only 0 should match if pattern is 0"); - assert!(!c.mode_bits_match(0, 0o444), - "Exact: only 0 should match if pattern is 0"); - assert!(c.mode_bits_match(0o444, 0o444), - "Exact: identical bits should match"); - assert!(!c.mode_bits_match(0o444, 0o777), - "Exact: non-identical bits should fail"); - assert!(c.mode_bits_match(0o444, 0o70444), - "Exact:high-end bits should be ignored"); - - + assert!( + c.mode_bits_match(0, 0), + "Exact: only 0 should match if pattern is 0" + ); + assert!( + !c.mode_bits_match(0, 0o444), + "Exact: only 0 should match if pattern is 0" + ); + assert!( + c.mode_bits_match(0o444, 0o444), + "Exact: identical bits should match" + ); + assert!( + !c.mode_bits_match(0o444, 0o777), + "Exact: non-identical bits should fail" + ); + assert!( + c.mode_bits_match(0o444, 0o70444), + "Exact:high-end bits should be ignored" + ); let c = ComparisonType::AtLeast; - assert!(c.mode_bits_match(0, 0), - "AtLeast: anything should match if pattern is 0"); - assert!(c.mode_bits_match(0, 0o444), - "AtLeast: anything should match if pattern is 0"); - assert!(c.mode_bits_match(0o444, 0o777), - "AtLeast: identical bits should match"); - assert!(c.mode_bits_match(0o444, 0o777), - "AtLeast: extra bits should match"); - assert!(!c.mode_bits_match(0o444, 0o700), - "AtLeast: missing bits should fail"); - assert!(c.mode_bits_match(0o444, 0o70444), - "AtLeast: high-end bits should be ignored"); + assert!( + c.mode_bits_match(0, 0), + "AtLeast: anything should match if pattern is 0" + ); + assert!( + c.mode_bits_match(0, 0o444), + "AtLeast: anything should match if pattern is 0" + ); + assert!( + c.mode_bits_match(0o444, 0o777), + "AtLeast: identical bits should match" + ); + assert!( + c.mode_bits_match(0o444, 0o777), + "AtLeast: extra bits should match" + ); + assert!( + !c.mode_bits_match(0o444, 0o700), + "AtLeast: missing bits should fail" + ); + assert!( + c.mode_bits_match(0o444, 0o70444), + "AtLeast: high-end bits should be ignored" + ); let c = ComparisonType::AnyOf; - assert!(c.mode_bits_match(0, 0), - "AnyOf: anything should match if pattern is 0"); - assert!(c.mode_bits_match(0, 0o444), - "AnyOf: anything should match if pattern is 0"); - assert!(c.mode_bits_match(0o444, 0o777), - "AnyOf: identical bits should match"); - assert!(c.mode_bits_match(0o444, 0o777), - "AnyOf: extra bits should match"); - assert!(c.mode_bits_match(0o777, 0o001), - "AnyOf: anything should match as long as it has one bit in common"); - assert!(!c.mode_bits_match(0o010, 0o001), - "AnyOf: no matching bits shouldn't match"); - assert!(c.mode_bits_match(0o444, 0o70444), - "AnyOf: high-end bits should be ignored"); + assert!( + c.mode_bits_match(0, 0), + "AnyOf: anything should match if pattern is 0" + ); + assert!( + c.mode_bits_match(0, 0o444), + "AnyOf: anything should match if pattern is 0" + ); + assert!( + c.mode_bits_match(0o444, 0o777), + "AnyOf: identical bits should match" + ); + assert!( + c.mode_bits_match(0o444, 0o777), + "AnyOf: extra bits should match" + ); + assert!( + c.mode_bits_match(0o777, 0o001), + "AnyOf: anything should match as long as it has one bit in common" + ); + assert!( + !c.mode_bits_match(0o010, 0o001), + "AnyOf: no matching bits shouldn't match" + ); + assert!( + c.mode_bits_match(0o444, 0o70444), + "AnyOf: high-end bits should be ignored" + ); } #[test] @@ -492,11 +605,15 @@ mod tests { let deps = FakeDependencies::new(); let matcher = PermMatcher::new("-u+r").unwrap(); - assert!(matcher.matches(&file_info, &mut deps.new_matcher_io()), - "user-readable pattern should match file"); + assert!( + matcher.matches(&file_info, &mut deps.new_matcher_io()), + "user-readable pattern should match file" + ); let matcher = PermMatcher::new("-u+x").unwrap(); - assert!(!matcher.matches(&file_info, &mut deps.new_matcher_io()), - "user-executable pattern should not match file"); + assert!( + !matcher.matches(&file_info, &mut deps.new_matcher_io()), + "user-executable pattern should not match file" + ); } } diff --git a/src/find/matchers/printer.rs b/src/find/matchers/printer.rs index 7cb71c8..5bd3d3a 100644 --- a/src/find/matchers/printer.rs +++ b/src/find/matchers/printer.rs @@ -23,10 +23,12 @@ impl Printer { impl Matcher for Printer { fn matches(&self, file_info: &DirEntry, matcher_io: &mut MatcherIO) -> bool { - writeln!(matcher_io.deps.get_output().borrow_mut(), - "{}", - file_info.path().to_string_lossy()) - .unwrap(); + writeln!( + matcher_io.deps.get_output().borrow_mut(), + "{}", + file_info.path().to_string_lossy() + ) + .unwrap(); true } @@ -38,11 +40,11 @@ impl Matcher for Printer { #[cfg(test)] mod tests { + use super::*; use crate::find::matchers::tests::get_dir_entry_for; use crate::find::matchers::Matcher; - use crate::find::tests::FakeDependencies; use crate::find::tests::fix_up_slashes; - use super::*; + use crate::find::tests::FakeDependencies; #[test] fn prints() { @@ -51,7 +53,9 @@ mod tests { let matcher = Printer::new(); let deps = FakeDependencies::new(); assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io())); - assert_eq!(fix_up_slashes("./test_data/simple/abbbc\n"), - deps.get_output_as_string()); + assert_eq!( + fix_up_slashes("./test_data/simple/abbbc\n"), + deps.get_output_as_string() + ); } } diff --git a/src/find/matchers/prune.rs b/src/find/matchers/prune.rs index abe32da..2b8f774 100644 --- a/src/find/matchers/prune.rs +++ b/src/find/matchers/prune.rs @@ -30,10 +30,10 @@ impl Matcher for PruneMatcher { #[cfg(test)] mod tests { - use crate::find::matchers::Matcher; - use crate::find::matchers::tests::get_dir_entry_for; - use crate::find::tests::FakeDependencies; use super::*; + use crate::find::matchers::tests::get_dir_entry_for; + use crate::find::matchers::Matcher; + use crate::find::tests::FakeDependencies; #[test] fn file_type_matcher() { diff --git a/src/find/matchers/size.rs b/src/find/matchers/size.rs index 866fc05..3c2340d 100644 --- a/src/find/matchers/size.rs +++ b/src/find/matchers/size.rs @@ -32,9 +32,11 @@ impl FromStr for Unit { "M" => Unit::MebiByte, "G" => Unit::GibiByte, _ => { - return Err(From::from(format!("Invalid suffix {} for -size. Only allowed \ - values are , b, c, w, k, M or G", - s))); + return Err(From::from(format!( + "Invalid suffix {} for -size. Only allowed \ + values are , b, c, w, k, M or G", + s + ))); } }) } @@ -70,18 +72,20 @@ pub struct SizeMatcher { } impl SizeMatcher { - pub fn new(value_to_match: ComparableValue, - suffix_string: &str) - -> Result> { + pub fn new( + value_to_match: ComparableValue, + suffix_string: &str, + ) -> Result> { Ok(SizeMatcher { unit: suffix_string.parse()?, value_to_match: value_to_match, }) } - pub fn new_box(value_to_match: ComparableValue, - suffix_string: &str) - -> Result, Box> { + pub fn new_box( + value_to_match: ComparableValue, + suffix_string: &str, + ) -> Result, Box> { Ok(Box::new(SizeMatcher::new(value_to_match, suffix_string)?)) } } @@ -89,16 +93,17 @@ impl SizeMatcher { impl Matcher for SizeMatcher { fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool { match file_info.metadata() { - Ok(metadata) => { - self.value_to_match - .matches(byte_size_to_unit_size(self.unit, metadata.len())) - } + Ok(metadata) => self + .value_to_match + .matches(byte_size_to_unit_size(self.unit, metadata.len())), Err(e) => { - writeln!(&mut stderr(), - "Error getting file size for {}: {}", - file_info.path().to_string_lossy(), - e) - .unwrap(); + writeln!( + &mut stderr(), + "Error getting file size for {}: {}", + file_info.path().to_string_lossy(), + e + ) + .unwrap(); false } } @@ -107,10 +112,10 @@ impl Matcher for SizeMatcher { #[cfg(test)] mod tests { - use crate::find::matchers::{ComparableValue, Matcher}; - use crate::find::matchers::tests::get_dir_entry_for; - use crate::find::tests::FakeDependencies; use super::*; + use crate::find::matchers::tests::get_dir_entry_for; + use crate::find::matchers::{ComparableValue, Matcher}; + use crate::find::tests::FakeDependencies; // need to explicitly use non-pub members use super::{byte_size_to_unit_size, Unit}; @@ -125,8 +130,10 @@ mod tests { assert_eq!(byte_size_to_unit_size(Unit::Block, 1025), 3); assert_eq!(byte_size_to_unit_size(Unit::KibiByte, 1025), 2); assert_eq!(byte_size_to_unit_size(Unit::MebiByte, 1024 * 1024 + 1), 2); - assert_eq!(byte_size_to_unit_size(Unit::GibiByte, 1024 * 1024 * 1024 + 1), - 2); + assert_eq!( + byte_size_to_unit_size(Unit::GibiByte, 1024 * 1024 * 1024 + 1), + 2 + ); } #[test] @@ -136,18 +143,24 @@ mod tests { assert_eq!(byte_size_to_unit_size("b".parse().unwrap(), 513), 2); assert_eq!(byte_size_to_unit_size("".parse().unwrap(), 513), 2); assert_eq!(byte_size_to_unit_size("k".parse().unwrap(), 1025), 2); - assert_eq!(byte_size_to_unit_size("M".parse().unwrap(), 1024 * 1024 + 1), - 2); - assert_eq!(byte_size_to_unit_size("G".parse().unwrap(), 2024 * 1024 * 1024 + 1), - 2); + assert_eq!( + byte_size_to_unit_size("M".parse().unwrap(), 1024 * 1024 + 1), + 2 + ); + assert_eq!( + byte_size_to_unit_size("G".parse().unwrap(), 2024 * 1024 * 1024 + 1), + 2 + ); } #[test] fn size_matcher_bad_unit() { if let Err(e) = SizeMatcher::new(ComparableValue::EqualTo(2), "xyz") { - assert!(e.description().contains("Invalid suffix") && e.description().contains("xyz"), - "bad description: {}", - e); + assert!( + e.description().contains("Invalid suffix") && e.description().contains("xyz"), + "bad description: {}", + e + ); } else { panic!("parsing a unit string should fail"); } @@ -161,9 +174,13 @@ mod tests { let equal_to_1_blocks = SizeMatcher::new(ComparableValue::EqualTo(1), "b").unwrap(); let deps = FakeDependencies::new(); - assert!(!equal_to_2_blocks.matches(&file_info, &mut deps.new_matcher_io()), - "512-byte file should not match size of 2 blocks"); - assert!(equal_to_1_blocks.matches(&file_info, &mut deps.new_matcher_io()), - "512-byte file should match size of 1 block"); + assert!( + !equal_to_2_blocks.matches(&file_info, &mut deps.new_matcher_io()), + "512-byte file should not match size of 2 blocks" + ); + assert!( + equal_to_1_blocks.matches(&file_info, &mut deps.new_matcher_io()), + "512-byte file should match size of 1 block" + ); } } diff --git a/src/find/matchers/time.rs b/src/find/matchers/time.rs index 1a84c5c..7b90a38 100644 --- a/src/find/matchers/time.rs +++ b/src/find/matchers/time.rs @@ -23,7 +23,9 @@ pub struct NewerMatcher { impl NewerMatcher { pub fn new(path_to_file: &str) -> Result> { let metadata = fs::metadata(path_to_file)?; - Ok(NewerMatcher { given_modification_time: metadata.modified()? }) + Ok(NewerMatcher { + given_modification_time: metadata.modified()?, + }) } pub fn new_box(path_to_file: &str) -> Result, Box> { @@ -38,7 +40,10 @@ impl NewerMatcher { // and returns an Err (with a duration) otherwise. So if this_time > // given_modification_time (in which case we want to return true) then // duration_since will return an error. - Ok(self.given_modification_time.duration_since(this_time).is_err()) + Ok(self + .given_modification_time + .duration_since(this_time) + .is_err()) } } @@ -46,11 +51,13 @@ impl Matcher for NewerMatcher { fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool { match self.matches_impl(file_info) { Err(e) => { - writeln!(&mut stderr(), - "Error getting modification time for {}: {}", - file_info.path().to_string_lossy(), - e) - .unwrap(); + writeln!( + &mut stderr(), + "Error getting modification time for {}: {}", + file_info.path().to_string_lossy(), + e + ) + .unwrap(); false } Ok(t) => t, @@ -86,12 +93,14 @@ impl Matcher for FileTimeMatcher { fn matches(&self, file_info: &DirEntry, matcher_io: &mut MatcherIO) -> bool { match self.matches_impl(file_info, matcher_io.now()) { Err(e) => { - writeln!(&mut stderr(), - "Error getting {:?} time for {}: {}", - self.file_time_type, - file_info.path().to_string_lossy(), - e) - .unwrap(); + writeln!( + &mut stderr(), + "Error getting {:?} time for {}: {}", + self.file_time_type, + file_info.path().to_string_lossy(), + e + ) + .unwrap(); false } Ok(t) => t, @@ -99,8 +108,6 @@ impl Matcher for FileTimeMatcher { } } - - impl FileTimeMatcher { /// Impementation of matches that returns a result, allowing use to use try! /// to deal with the errors. @@ -147,10 +154,10 @@ mod tests { use tempdir::TempDir; use walkdir::DirEntry; - use crate::find::matchers::{ComparableValue, Matcher}; - use crate::find::matchers::tests::get_dir_entry_for; - use crate::find::tests::FakeDependencies; use super::*; + use crate::find::matchers::tests::get_dir_entry_for; + use crate::find::matchers::{ComparableValue, Matcher}; + use crate::find::tests::FakeDependencies; #[test] fn newer_matcher() { @@ -170,12 +177,18 @@ mod tests { let matcher_for_old = NewerMatcher::new(&old_file.path().to_string_lossy()).unwrap(); let deps = FakeDependencies::new(); - assert!(!matcher_for_new.matches(&old_file, &mut deps.new_matcher_io()), - "old_file shouldn't be newer than new_dir"); - assert!(matcher_for_old.matches(&new_file, &mut deps.new_matcher_io()), - "new_file should be newer than old_dir"); - assert!(!matcher_for_old.matches(&old_file, &mut deps.new_matcher_io()), - "old_file shouldn't be newer than itself"); + assert!( + !matcher_for_new.matches(&old_file, &mut deps.new_matcher_io()), + "old_file shouldn't be newer than new_dir" + ); + assert!( + matcher_for_old.matches(&new_file, &mut deps.new_matcher_io()), + "new_file should be newer than old_dir" + ); + assert!( + !matcher_for_old.matches(&old_file, &mut deps.new_matcher_io()), + "old_file shouldn't be newer than itself" + ); } #[test] @@ -185,67 +198,96 @@ mod tests { let files_mtime = file.metadata().unwrap().modified().unwrap(); - let exactly_one_day_matcher = FileTimeMatcher::new(FileTimeType::Modified, - ComparableValue::EqualTo(1)); - let more_than_one_day_matcher = FileTimeMatcher::new(FileTimeType::Modified, - ComparableValue::MoreThan(1)); - let less_than_one_day_matcher = FileTimeMatcher::new(FileTimeType::Modified, - ComparableValue::LessThan(1)); - let zero_day_matcher = FileTimeMatcher::new(FileTimeType::Modified, - ComparableValue::EqualTo(0)); + let exactly_one_day_matcher = + FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::EqualTo(1)); + let more_than_one_day_matcher = + FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::MoreThan(1)); + let less_than_one_day_matcher = + FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::LessThan(1)); + let zero_day_matcher = + FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::EqualTo(0)); // set "now" to 2 days after the file was modified. let mut deps = FakeDependencies::new(); deps.set_time(files_mtime + Duration::new(2 * super::SECONDS_PER_DAY as u64, 0)); - assert!(!exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "2 day old file shouldn't match exactly 1 day old"); - assert!(more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "2 day old file should match more than 1 day old"); - assert!(!less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "2 day old file shouldn't match less than 1 day old"); - assert!(!zero_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "2 day old file shouldn't match exactly 0 days old"); + assert!( + !exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "2 day old file shouldn't match exactly 1 day old" + ); + assert!( + more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "2 day old file should match more than 1 day old" + ); + assert!( + !less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "2 day old file shouldn't match less than 1 day old" + ); + assert!( + !zero_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "2 day old file shouldn't match exactly 0 days old" + ); // set "now" to 1 day after the file was modified. deps.set_time(files_mtime + Duration::new((3 * super::SECONDS_PER_DAY / 2) as u64, 0)); - assert!(exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "1 day old file should match exactly 1 day old"); - assert!(!more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "1 day old file shouldn't match more than 1 day old"); - assert!(!less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "1 day old file shouldn't match less than 1 day old"); - assert!(!zero_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "1 day old file shouldn't match exactly 0 days old"); + assert!( + exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "1 day old file should match exactly 1 day old" + ); + assert!( + !more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "1 day old file shouldn't match more than 1 day old" + ); + assert!( + !less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "1 day old file shouldn't match less than 1 day old" + ); + assert!( + !zero_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "1 day old file shouldn't match exactly 0 days old" + ); // set "now" to exactly the same time file was modified. deps.set_time(files_mtime); - assert!(!exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "0 day old file shouldn't match exactly 1 day old"); - assert!(!more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "0 day old file shouldn't match more than 1 day old"); - assert!(less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "0 day old file should match less than 1 day old"); - assert!(zero_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "0 day old file should match exactly 0 days old"); - + assert!( + !exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "0 day old file shouldn't match exactly 1 day old" + ); + assert!( + !more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "0 day old file shouldn't match more than 1 day old" + ); + assert!( + less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "0 day old file should match less than 1 day old" + ); + assert!( + zero_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "0 day old file should match exactly 0 days old" + ); // set "now" to a second before the file was modified (e.g. the file was // modified after find started running deps.set_time(files_mtime - Duration::new(1 as u64, 0)); - assert!(!exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "future-modified file shouldn'1 match exactly 1 day old"); - assert!(!more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "future-modified file shouldn't match more than 1 day old"); - assert!(less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "future-modified file should match less than 1 day old"); - assert!(!zero_day_matcher.matches(&file, &mut deps.new_matcher_io()), - "future-modified file shouldn't match exactly 0 days old"); - + assert!( + !exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "future-modified file shouldn'1 match exactly 1 day old" + ); + assert!( + !more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "future-modified file shouldn't match more than 1 day old" + ); + assert!( + less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "future-modified file should match less than 1 day old" + ); + assert!( + !zero_day_matcher.matches(&file, &mut deps.new_matcher_io()), + "future-modified file shouldn't match exactly 0 days old" + ); } #[test] fn file_time_matcher_modified_created_accessed() { - let temp_dir = TempDir::new("file_time_matcher_modified_created_accessed").unwrap(); // No easy way to independently set file times. So create it - setting creation time @@ -266,12 +308,14 @@ mod tests { // write to the file - changing the modifiation and potentially the accessed time let mut buffer = [0; 10]; { - let mut f = - OpenOptions::new().read(true).write(true).open(&foo_path).expect("open temp file"); + let mut f = OpenOptions::new() + .read(true) + .write(true) + .open(&foo_path) + .expect("open temp file"); let _ = f.write(&mut buffer); } - thread::sleep(Duration::from_secs(2)); // read the file agaion - potentially changing accessed time { @@ -302,22 +346,28 @@ mod tests { } /// helper function for file_time_matcher_modified_created_accessed - fn test_matcher_for_file_time_type(file_info: &DirEntry, - file_time: SystemTime, - file_time_type: FileTimeType) { + fn test_matcher_for_file_time_type( + file_info: &DirEntry, + file_time: SystemTime, + file_time_type: FileTimeType, + ) { { let matcher = FileTimeMatcher::new(file_time_type, ComparableValue::EqualTo(0)); let mut deps = FakeDependencies::new(); deps.set_time(file_time); - assert!(matcher.matches(&file_info, &mut deps.new_matcher_io()), - "{:?} time matcher should match", - file_time_type); + assert!( + matcher.matches(&file_info, &mut deps.new_matcher_io()), + "{:?} time matcher should match", + file_time_type + ); deps.set_time(file_time - Duration::from_secs(1)); - assert!(!matcher.matches(&file_info, &mut deps.new_matcher_io()), - "{:?} time matcher shouldn't match a second before", - file_time_type); + assert!( + !matcher.matches(&file_info, &mut deps.new_matcher_io()), + "{:?} time matcher shouldn't match a second before", + file_time_type + ); } } } diff --git a/src/find/matchers/type_matcher.rs b/src/find/matchers/type_matcher.rs index e345a8f..4f5d211 100644 --- a/src/find/matchers/type_matcher.rs +++ b/src/find/matchers/type_matcher.rs @@ -21,11 +21,21 @@ impl TypeMatcher { "f" => FileType::is_file, "d" => FileType::is_dir, "b" | "c" | "p" | "l" | "s" | "D" => { - return Err(From::from(format!("Type argument {} not supported yet", type_string))) + return Err(From::from(format!( + "Type argument {} not supported yet", + type_string + ))) + } + _ => { + return Err(From::from(format!( + "Unrecognised type argument {}", + type_string + ))) } - _ => return Err(From::from(format!("Unrecognised type argument {}", type_string))), }; - Ok(TypeMatcher { file_type_fn: function }) + Ok(TypeMatcher { + file_type_fn: function, + }) } pub fn new_box(type_string: &str) -> Result, Box> { @@ -41,10 +51,10 @@ impl Matcher for TypeMatcher { #[cfg(test)] mod tests { - use crate::find::matchers::Matcher; - use crate::find::matchers::tests::get_dir_entry_for; - use crate::find::tests::FakeDependencies; use super::*; + use crate::find::matchers::tests::get_dir_entry_for; + use crate::find::matchers::Matcher; + use crate::find::tests::FakeDependencies; #[test] fn file_type_matcher() { diff --git a/src/find/mod.rs b/src/find/mod.rs index b844f5a..dfccbcd 100644 --- a/src/find/mod.rs +++ b/src/find/mod.rs @@ -8,7 +8,7 @@ pub mod matchers; use std::cell::RefCell; use std::error::Error; -use std::io::{Write, stderr, stdout}; +use std::io::{stderr, stdout, Write}; use std::rc::Rc; use std::time::SystemTime; use walkdir::WalkDir; @@ -33,7 +33,6 @@ impl Default for Config { } } - /// Trait that encapsulates various dependencies (output, clocks, etc.) that we /// might want to fake out for unit tests. pub trait Dependencies<'a> { @@ -79,8 +78,11 @@ fn parse_args(args: &[&str]) -> Result> { let mut i = 0; let mut config = Config::default(); - while i < args.len() && (args[i] == "-" || !args[i].starts_with('-')) && args[i] != "!" && - args[i] != "(" { + while i < args.len() + && (args[i] == "-" || !args[i].starts_with('-')) + && args[i] != "!" + && args[i] != "(" + { paths.push(args[i].to_string()); i += 1; } @@ -95,12 +97,12 @@ fn parse_args(args: &[&str]) -> Result> { }) } -fn process_dir<'a>(dir: &str, - config: &Config, - deps: &'a Dependencies<'a>, - matcher: &Box) - -> Result> { - +fn process_dir<'a>( + dir: &str, + config: &Config, + deps: &'a Dependencies<'a>, + matcher: &Box, +) -> Result> { let mut found_count: u64 = 0; let mut walkdir = WalkDir::new(dir) .contents_first(config.depth_first) @@ -133,7 +135,6 @@ fn process_dir<'a>(dir: &str, Ok(found_count) } - fn do_find<'a>(args: &[&str], deps: &'a Dependencies<'a>) -> Result> { let paths_and_matcher = parse_args(args)?; if paths_and_matcher.config.help_requested { @@ -142,16 +143,19 @@ fn do_find<'a>(args: &[&str], deps: &'a Dependencies<'a>) -> Result(args: &[&str], deps: &'a Dependencies<'a>) -> i32 { - match do_find(&args[1..], deps) { Ok(_) => 0, Err(e) => { @@ -204,7 +208,6 @@ pub fn find_main<'a>(args: &[&str], deps: &'a Dependencies<'a>) -> i32 { #[cfg(test)] mod tests { - use std::cell::RefCell; use std::fs; use std::io::{Cursor, Read, Write}; @@ -288,151 +291,229 @@ mod tests { } } - #[test] fn find_main_not_depth_first() { let deps = FakeDependencies::new(); - - let rc = find_main(&["find", &fix_up_slashes("./test_data/simple"), "-sorted"], - &deps); + let rc = find_main( + &["find", &fix_up_slashes("./test_data/simple"), "-sorted"], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple\n\ - ./test_data/simple/abbbc\n\ - ./test_data/simple/subdir\n\ - ./test_data/simple/subdir/ABBBC\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes( + "./test_data/simple\n\ + ./test_data/simple/abbbc\n\ + ./test_data/simple/subdir\n\ + ./test_data/simple/subdir/ABBBC\n" + ) + ); } #[test] fn find_main_depth_first() { let deps = FakeDependencies::new(); - - let rc = find_main(&["find", &fix_up_slashes("./test_data/simple"), "-sorted", "-depth"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/simple"), + "-sorted", + "-depth", + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple/abbbc\n\ - ./test_data/simple/subdir/ABBBC\n\ - ./test_data/simple/subdir\n\ - ./test_data/simple\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes( + "./test_data/simple/abbbc\n\ + ./test_data/simple/subdir/ABBBC\n\ + ./test_data/simple/subdir\n\ + ./test_data/simple\n" + ) + ); } #[test] fn find_maxdepth() { let deps = FakeDependencies::new(); - let rc = - find_main(&["find", &fix_up_slashes("./test_data/depth"), "-sorted", "-maxdepth", "2"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/depth"), + "-sorted", + "-maxdepth", + "2", + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/depth\n\ - ./test_data/depth/1\n\ - ./test_data/depth/1/2\n\ - ./test_data/depth/1/f1\n\ - ./test_data/depth/f0\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes( + "./test_data/depth\n\ + ./test_data/depth/1\n\ + ./test_data/depth/1/2\n\ + ./test_data/depth/1/f1\n\ + ./test_data/depth/f0\n" + ) + ); } #[test] fn find_maxdepth_depth_first() { let deps = FakeDependencies::new(); - let rc = find_main(&["find", - &fix_up_slashes("./test_data/depth"), - "-sorted", - "-maxdepth", - "2", - "-depth"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/depth"), + "-sorted", + "-maxdepth", + "2", + "-depth", + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/depth/1/2\n\ - ./test_data/depth/1/f1\n\ - ./test_data/depth/1\n\ - ./test_data/depth/f0\n\ - ./test_data/depth\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes( + "./test_data/depth/1/2\n\ + ./test_data/depth/1/f1\n\ + ./test_data/depth/1\n\ + ./test_data/depth/f0\n\ + ./test_data/depth\n" + ) + ); } #[test] fn find_prune() { let deps = FakeDependencies::new(); - let rc = find_main(&["find", - &fix_up_slashes("./test_data/depth"), - "-sorted", - "-print", - ",", - "-name", - "1", - "-prune"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/depth"), + "-sorted", + "-print", + ",", + "-name", + "1", + "-prune", + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/depth\n\ - ./test_data/depth/1\n\ - ./test_data/depth/f0\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes( + "./test_data/depth\n\ + ./test_data/depth/1\n\ + ./test_data/depth/f0\n" + ) + ); } #[test] fn find_zero_maxdepth() { let deps = FakeDependencies::new(); - let rc = find_main(&["find", &fix_up_slashes("./test_data/depth"), "-maxdepth", "0"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/depth"), + "-maxdepth", + "0", + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/depth\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/depth\n") + ); } #[test] fn find_zero_maxdepth_depth_first() { let deps = FakeDependencies::new(); - let rc = - find_main(&["find", &fix_up_slashes("./test_data/depth"), "-maxdepth", "0", "-depth"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/depth"), + "-maxdepth", + "0", + "-depth", + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/depth\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/depth\n") + ); } #[test] fn find_mindepth() { let deps = FakeDependencies::new(); - let rc = - find_main(&["find", &fix_up_slashes("./test_data/depth"), "-sorted", "-mindepth", "3"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/depth"), + "-sorted", + "-mindepth", + "3", + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/depth/1/2/3\n\ - ./test_data/depth/1/2/3/f3\n\ - ./test_data/depth/1/2/f2\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes( + "./test_data/depth/1/2/3\n\ + ./test_data/depth/1/2/3/f3\n\ + ./test_data/depth/1/2/f2\n" + ) + ); } #[test] fn find_mindepth_depth_first() { let deps = FakeDependencies::new(); - let rc = find_main(&["find", - &fix_up_slashes("./test_data/depth"), - "-sorted", - "-mindepth", - "3", - "-depth"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/depth"), + "-sorted", + "-mindepth", + "3", + "-depth", + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/depth/1/2/3/f3\n\ - ./test_data/depth/1/2/3\n\ - ./test_data/depth/1/2/f2\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes( + "./test_data/depth/1/2/3/f3\n\ + ./test_data/depth/1/2/3\n\ + ./test_data/depth/1/2/f2\n" + ) + ); } #[test] @@ -443,24 +524,33 @@ mod tests { let deps = FakeDependencies::new(); - - let rc = find_main(&["find", - &new_dir.path().to_string_lossy(), - "-newer", - &fix_up_slashes("./test_data/simple/abbbc")], - &deps); + let rc = find_main( + &[ + "find", + &new_dir.path().to_string_lossy(), + "-newer", + &fix_up_slashes("./test_data/simple/abbbc"), + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - (&new_dir).path().to_string_lossy().to_string() + "\n"); + assert_eq!( + deps.get_output_as_string(), + (&new_dir).path().to_string_lossy().to_string() + "\n" + ); // now do it the other way around, and nothing should be output let deps = FakeDependencies::new(); - let rc = find_main(&["find", - &fix_up_slashes("./test_data/simple/abbbc"), - "-newer", - &new_dir.path().to_string_lossy()], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/simple/abbbc"), + "-newer", + &new_dir.path().to_string_lossy(), + ], + &deps, + ); assert_eq!(rc, 0); assert_eq!(deps.get_output_as_string(), ""); @@ -506,17 +596,23 @@ mod tests { let mut deps = FakeDependencies::new(); deps.set_time(file_time); - let rc = find_main(&["find", - &fix_up_slashes("./test_data/simple/subdir"), - "-type", - "f", - arg, - "0"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/simple/subdir"), + "-type", + "f", + arg, + "0", + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/simple/subdir/ABBBC\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/simple/subdir/ABBBC\n") + ); } // now Check file time doesn't match a file that's too new @@ -524,8 +620,10 @@ mod tests { let mut deps = FakeDependencies::new(); deps.set_time(file_time - Duration::from_secs(1)); - let rc = find_main(&["find", "./test_data/simple/subdir", "-type", "f", arg, "0"], - &deps); + let rc = find_main( + &["find", "./test_data/simple/subdir", "-type", "f", arg, "0"], + &deps, + ); assert_eq!(rc, 0); assert_eq!(deps.get_output_as_string(), ""); @@ -537,20 +635,31 @@ mod tests { let deps = FakeDependencies::new(); // only look at files because the "size" of a directory is a system (and filesystem) // dependent thing and we want these tests to be universal. - let rc = - find_main(&["find", &fix_up_slashes("./test_data/size"), "-type", "f", "-size", "1b"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/size"), + "-type", + "f", + "-size", + "1b", + ], + &deps, + ); assert_eq!(rc, 0); - assert_eq!(deps.get_output_as_string(), - fix_up_slashes("./test_data/size/512bytes\n")); + assert_eq!( + deps.get_output_as_string(), + fix_up_slashes("./test_data/size/512bytes\n") + ); let deps = FakeDependencies::new(); - let rc = find_main(&["find", "./test_data/size", "-type", "f", "-size", "+1b"], - &deps); + let rc = find_main( + &["find", "./test_data/size", "-type", "f", "-size", "+1b"], + &deps, + ); assert_eq!(rc, 0); assert_eq!(deps.get_output_as_string(), ""); - } } diff --git a/src/testing/commandline/main.rs b/src/testing/commandline/main.rs index 2d813ff..447f767 100644 --- a/src/testing/commandline/main.rs +++ b/src/testing/commandline/main.rs @@ -21,8 +21,9 @@ struct Config { } fn open_file(destination_dir: &str) -> File { - let mut file_number = - fs::read_dir(destination_dir).expect("failed to read destination").count(); + let mut file_number = fs::read_dir(destination_dir) + .expect("failed to read destination") + .count(); loop { file_number += 1; @@ -31,7 +32,8 @@ fn open_file(destination_dir: &str) -> File { if let Ok(f) = OpenOptions::new() .write(true) .create_new(true) - .open(file_path) { + .open(file_path) + { return f; } } @@ -62,13 +64,15 @@ fn main() { // first two args are going to be the path to this executable and // the destination_dir we want to write to. Don't write either of those // as they'll be non-deterministic. - f.write_fmt(format_args!("cwd={}\nargs=\n", - env::current_dir().unwrap().to_string_lossy())) - .expect("failed to write to file"); + f.write_fmt(format_args!( + "cwd={}\nargs=\n", + env::current_dir().unwrap().to_string_lossy() + )) + .expect("failed to write to file"); for arg in &args[2..] { - f.write_fmt(format_args!("{}\n", arg)).expect("failed to write to file"); + f.write_fmt(format_args!("{}\n", arg)) + .expect("failed to write to file"); } - } std::process::exit(if config.exit_with_failure { 2 } else { 0 }); } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index eb372d0..aa8de37 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -4,7 +4,6 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. - // As this module is included by all the integration tests, any function used // in one test but not another can cause a dead code warning. #[allow(dead_code)] diff --git a/tests/common/test_helpers.rs b/tests/common/test_helpers.rs index 4c2680a..f2016fe 100644 --- a/tests/common/test_helpers.rs +++ b/tests/common/test_helpers.rs @@ -4,7 +4,6 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. - use std::cell::RefCell; use std::env; use std::io::{Cursor, Read, Write}; @@ -55,7 +54,6 @@ impl<'a> Dependencies<'a> for FakeDependencies { } pub fn path_to_testing_commandline() -> String { - let mut path_to_use = env::current_exe() // this will be something along the lines of /my/homedir/findutils/target/debug/deps/findutils-5532804878869ef1 .expect("can't find path of this executable") @@ -67,8 +65,7 @@ pub fn path_to_testing_commandline() -> String { path_to_use.pop(); } path_to_use = path_to_use.join("testing-commandline"); - path_to_use.to_string_lossy() - .to_string() + path_to_use.to_string_lossy().to_string() } #[cfg(windows)] diff --git a/tests/exec_unit_tests.rs b/tests/exec_unit_tests.rs index c32dc70..a31e02d 100644 --- a/tests/exec_unit_tests.rs +++ b/tests/exec_unit_tests.rs @@ -4,7 +4,6 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. - /// ! This file contains what would be normally be unit tests for find::matchers::exec. /// ! But as the tests require running an external executable, they need to be run /// ! as integration tests so we can ensure that our testing-commandline binary @@ -13,70 +12,78 @@ extern crate findutils; extern crate tempdir; extern crate walkdir; - use std::env; use std::fs::File; use std::io::Read; use tempdir::TempDir; use walkdir::WalkDir; - -use findutils::find::matchers::Matcher; -use findutils::find::matchers::exec::*; use common::test_helpers::*; +use findutils::find::matchers::exec::*; +use findutils::find::matchers::Matcher; mod common; #[test] fn matching_executes_code() { - let temp_dir = TempDir::new("matching_executes_code").unwrap(); let temp_dir_path = temp_dir.path().to_string_lossy(); let abbbc = get_dir_entry_for("test_data/simple", "abbbc"); - let matcher = SingleExecMatcher::new(&path_to_testing_commandline(), - &vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"], - false) - .expect("Failed to create matcher"); + let matcher = SingleExecMatcher::new( + &path_to_testing_commandline(), + &vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"], + false, + ) + .expect("Failed to create matcher"); let deps = FakeDependencies::new(); assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io())); let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file"); let mut s = String::new(); - f.read_to_string(&mut s).expect("failed to read output file"); - assert_eq!(s, - fix_up_slashes(&format!("cwd={}\nargs=\nabc\ntest_data/simple/abbbc\nxyz\n", - env::current_dir().unwrap().to_string_lossy()))); + f.read_to_string(&mut s) + .expect("failed to read output file"); + assert_eq!( + s, + fix_up_slashes(&format!( + "cwd={}\nargs=\nabc\ntest_data/simple/abbbc\nxyz\n", + env::current_dir().unwrap().to_string_lossy() + )) + ); } #[test] fn matching_executes_code_in_files_directory() { - let temp_dir = TempDir::new("matching_executes_code_in_files_directory").unwrap(); let temp_dir_path = temp_dir.path().to_string_lossy(); let abbbc = get_dir_entry_for("test_data/simple", "abbbc"); - let matcher = SingleExecMatcher::new(&path_to_testing_commandline(), - &vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"], - true) - .expect("Failed to create matcher"); + let matcher = SingleExecMatcher::new( + &path_to_testing_commandline(), + &vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"], + true, + ) + .expect("Failed to create matcher"); let deps = FakeDependencies::new(); assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io())); let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file"); let mut s = String::new(); - f.read_to_string(&mut s).expect("failed to read output file"); - assert_eq!(s, - fix_up_slashes(&format!("cwd={}/test_data/simple\nargs=\nabc\n./abbbc\nxyz\n", - env::current_dir().unwrap().to_string_lossy()))); - + f.read_to_string(&mut s) + .expect("failed to read output file"); + assert_eq!( + s, + fix_up_slashes(&format!( + "cwd={}/test_data/simple\nargs=\nabc\n./abbbc\nxyz\n", + env::current_dir().unwrap().to_string_lossy() + )) + ); } #[test] /// Running "find . -execdir whatever \;" failed with a No such file or directory error. /// It's now fixed, and this is a regression test to check that it stays fixed. fn execdir_in_current_directory() { - let temp_dir = TempDir::new("execdir_in_current_directory").unwrap(); let temp_dir_path = temp_dir.path().to_string_lossy(); @@ -85,44 +92,59 @@ fn execdir_in_current_directory() { .next() .expect("iterator was empty") .expect("result wasn't OK"); - let matcher = SingleExecMatcher::new(&path_to_testing_commandline(), - &vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"], - true) - .expect("Failed to create matcher"); + let matcher = SingleExecMatcher::new( + &path_to_testing_commandline(), + &vec![temp_dir_path.as_ref(), "abc", "{}", "xyz"], + true, + ) + .expect("Failed to create matcher"); let deps = FakeDependencies::new(); assert!(matcher.matches(¤t_dir_entry, &mut deps.new_matcher_io())); let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file"); let mut s = String::new(); - f.read_to_string(&mut s).expect("failed to read output file"); - assert_eq!(s, - fix_up_slashes(&format!("cwd={}\nargs=\nabc\n./.\nxyz\n", - env::current_dir().unwrap().to_string_lossy()))); + f.read_to_string(&mut s) + .expect("failed to read output file"); + assert_eq!( + s, + fix_up_slashes(&format!( + "cwd={}\nargs=\nabc\n./.\nxyz\n", + env::current_dir().unwrap().to_string_lossy() + )) + ); } #[test] fn matching_fails_if_executable_fails() { - let temp_dir = TempDir::new("matching_fails_if_executable_fails").unwrap(); let temp_dir_path = temp_dir.path().to_string_lossy(); let abbbc = get_dir_entry_for("test_data/simple", "abbbc"); - let matcher = SingleExecMatcher::new(&path_to_testing_commandline(), - &vec![temp_dir_path.as_ref(), - "--exit_with_failure", - "abc", - "{}", - "xyz"], - true) - .expect("Failed to create matcher"); + let matcher = SingleExecMatcher::new( + &path_to_testing_commandline(), + &vec![ + temp_dir_path.as_ref(), + "--exit_with_failure", + "abc", + "{}", + "xyz", + ], + true, + ) + .expect("Failed to create matcher"); let deps = FakeDependencies::new(); assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io())); let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file"); let mut s = String::new(); - f.read_to_string(&mut s).expect("failed to read output file"); - assert_eq!(s, - fix_up_slashes(&format!("cwd={}/test_data/simple\nargs=\n--exit_with_failure\nabc\n.\ - /abbbc\nxyz\n", - env::current_dir().unwrap().to_string_lossy()))); + f.read_to_string(&mut s) + .expect("failed to read output file"); + assert_eq!( + s, + fix_up_slashes(&format!( + "cwd={}/test_data/simple\nargs=\n--exit_with_failure\nabc\n.\ + /abbbc\nxyz\n", + env::current_dir().unwrap().to_string_lossy() + )) + ); } diff --git a/tests/find_exec_tests.rs b/tests/find_exec_tests.rs index f24e434..da155df 100644 --- a/tests/find_exec_tests.rs +++ b/tests/find_exec_tests.rs @@ -4,7 +4,6 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. - /// ! This file contains what would be normally be unit tests for find::find_main /// ! related to -exec[dir] and ok[dir] clauses. /// ! But as the tests require running an external executable, they need to be run @@ -14,14 +13,13 @@ extern crate findutils; extern crate tempdir; extern crate walkdir; - use std::env; use std::fs::File; use std::io::Read; use tempdir::TempDir; -use findutils::find::find_main; use common::test_helpers::*; +use findutils::find::find_main; mod common; #[test] @@ -30,18 +28,22 @@ fn find_exec() { let temp_dir_path = temp_dir.path().to_string_lossy(); let deps = FakeDependencies::new(); - let rc = find_main(&["find", - &fix_up_slashes("./test_data/simple/subdir"), - "-type", - "f", - "-exec", - &path_to_testing_commandline(), - temp_dir_path.as_ref(), - "(", - "{}", - "-o", - ";"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/simple/subdir"), + "-type", + "f", + "-exec", + &path_to_testing_commandline(), + temp_dir_path.as_ref(), + "(", + "{}", + "-o", + ";", + ], + &deps, + ); assert_eq!(rc, 0); // exec has side effects, so we won't output anything unless -print is @@ -51,10 +53,15 @@ fn find_exec() { // check the executable ran as expected let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file"); let mut s = String::new(); - f.read_to_string(&mut s).expect("failed to read output file"); - assert_eq!(s, - fix_up_slashes(&format!("cwd={}\nargs=\n(\n./test_data/simple/subdir/ABBBC\n-o\n", - env::current_dir().unwrap().to_string_lossy()))); + f.read_to_string(&mut s) + .expect("failed to read output file"); + assert_eq!( + s, + fix_up_slashes(&format!( + "cwd={}\nargs=\n(\n./test_data/simple/subdir/ABBBC\n-o\n", + env::current_dir().unwrap().to_string_lossy() + )) + ); } #[test] @@ -64,18 +71,22 @@ fn find_execdir() { let deps = FakeDependencies::new(); // only look at files because the "size" of a directory is a system (and filesystem) // dependent thing and we want these tests to be universal. - let rc = find_main(&["find", - &fix_up_slashes("./test_data/simple/subdir"), - "-type", - "f", - "-execdir", - &path_to_testing_commandline(), - temp_dir_path.as_ref(), - ")", - "{}", - ",", - ";"], - &deps); + let rc = find_main( + &[ + "find", + &fix_up_slashes("./test_data/simple/subdir"), + "-type", + "f", + "-execdir", + &path_to_testing_commandline(), + temp_dir_path.as_ref(), + ")", + "{}", + ",", + ";", + ], + &deps, + ); assert_eq!(rc, 0); // exec has side effects, so we won't output anything unless -print is @@ -85,9 +96,13 @@ fn find_execdir() { // check the executable ran as expected let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file"); let mut s = String::new(); - f.read_to_string(&mut s).expect("failed to read output file"); - assert_eq!(s, - fix_up_slashes(&format!("cwd={}/test_data/simple/subdir\nargs=\n)\n./ABBBC\n,\n", - env::current_dir().unwrap().to_string_lossy()))); - + f.read_to_string(&mut s) + .expect("failed to read output file"); + assert_eq!( + s, + fix_up_slashes(&format!( + "cwd={}/test_data/simple/subdir\nargs=\n)\n./ABBBC\n,\n", + env::current_dir().unwrap().to_string_lossy() + )) + ); }