Format using rustfmt

This commit is contained in:
Alex Lyon
2019-04-24 03:06:42 -07:00
parent 2475c75247
commit 73d4ad5b8f
17 changed files with 1198 additions and 723 deletions
+1 -1
View File
@@ -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::<Vec<String>>();
+18 -14
View File
@@ -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<SingleExecMatcher, Box<Error>> {
let transformed_args = args.iter()
pub fn new(
executable: &str,
args: &[&str],
exec_in_parent_dir: bool,
) -> Result<SingleExecMatcher, Box<Error>> {
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<Matcher>, Box<Error>> {
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<Matcher>, Box<Error>> {
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.
+50 -30
View File
@@ -26,17 +26,20 @@ pub struct AndMatcher {
impl AndMatcher {
pub fn new(submatchers: Vec<Box<Matcher>>) -> 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<Matcher>) {
@@ -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<Box<Matcher>>) -> 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<Matcher>) {
// 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<Error>> {
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<Box<Matcher>>) -> 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<Matcher>) {
// 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<Error>> {
@@ -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<Matcher>,
@@ -311,7 +331,9 @@ pub struct NotMatcher {
impl NotMatcher {
pub fn new(submatcher: Box<Matcher>) -> NotMatcher {
NotMatcher { submatcher: submatcher }
NotMatcher {
submatcher: submatcher,
}
}
pub fn new_box(submatcher: Box<Matcher>) -> Box<NotMatcher> {
@@ -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");
+259 -156
View File
File diff suppressed because it is too large Load Diff
+12 -8
View File
@@ -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() {
+275 -158
View File
File diff suppressed because it is too large Load Diff
+12 -8
View File
@@ -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()
);
}
}
+3 -3
View File
@@ -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() {
+51 -34
View File
@@ -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 <nothing>, b, c, w, k, M or G",
s)));
return Err(From::from(format!(
"Invalid suffix {} for -size. Only allowed \
values are <nothing>, 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<SizeMatcher, Box<Error>> {
pub fn new(
value_to_match: ComparableValue,
suffix_string: &str,
) -> Result<SizeMatcher, Box<Error>> {
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<Matcher>, Box<Error>> {
pub fn new_box(
value_to_match: ComparableValue,
suffix_string: &str,
) -> Result<Box<Matcher>, Box<Error>> {
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"
);
}
}
+129 -79
View File
@@ -23,7 +23,9 @@ pub struct NewerMatcher {
impl NewerMatcher {
pub fn new(path_to_file: &str) -> Result<NewerMatcher, Box<Error>> {
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<Matcher>, Box<Error>> {
@@ -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
);
}
}
}
+16 -6
View File
@@ -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<Matcher>, Box<Error>> {
@@ -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() {
+239 -130
View File
File diff suppressed because it is too large Load Diff
+12 -8
View File
@@ -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 });
}
-1
View File
@@ -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)]
+1 -4
View File
@@ -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)]
+69 -47
View File
@@ -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(&current_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()
))
);
}
+51 -36
View File
@@ -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()
))
);
}