From d9cd28fab6b66b7728613fe28f310cf20ed22577 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Tue, 28 Sep 2021 00:16:23 +0200 Subject: [PATCH] test_tail: add tests for `--follow=name --disable-inotify` (polling) --- src/uu/tail/src/tail.rs | 2 + tests/by-util/test_tail.rs | 88 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index 551e428bf..3f85a249d 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -390,6 +390,7 @@ fn follow(readers: &mut Vec<(Box, &PathBuf)>, settings: &Settings) // notify::EventKind::Any => {} // EventKind::Access(AccessKind::Close(AccessMode::Write)) => {} EventKind::Create(CreateKind::File) + | EventKind::Create(CreateKind::Any) | EventKind::Modify(ModifyKind::Name(RenameMode::To)) => { // This triggers for e.g.: // Create: cp log.bak log.dat @@ -423,6 +424,7 @@ fn follow(readers: &mut Vec<(Box, &PathBuf)>, settings: &Settings) // EventKind::Modify(ModifyKind::Name(RenameMode::From)) => {} // EventKind::Modify(ModifyKind::Name(RenameMode::To)) => {} EventKind::Remove(RemoveKind::File) + | EventKind::Remove(RemoveKind::Any) | EventKind::Modify(ModifyKind::Name(RenameMode::From)) => { // This triggers for e.g.: // Create: cp log.dat log.bak diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index f5be060f7..2b75cb247 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -521,6 +521,51 @@ fn test_follow_name_create() { assert_eq!(buf_stderr, expected_stderr); } +#[test] +fn test_follow_name_create_polling() { + // This test triggers a remove/create event while `tail --follow=name --disable-inotify logfile` is running. + // cp logfile backup && rm logfile && sleep 1 && cp backup logfile + + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + + let source = FOLLOW_NAME_TXT; + let source_canonical = &at.plus(source); + let backup = at.plus_as_string("backup"); + + let expected_stdout = at.read(FOLLOW_NAME_EXP); + let expected_stderr = format!( + "{}: '{}' has been replaced; following new file\n", + ts.util_name, source + ); + + let args = ["--follow=name", "--disable-inotify", source]; + let mut p = ts.ucmd().args(&args).run_no_wait(); + + let delay = 750; + + std::fs::copy(&source_canonical, &backup).unwrap(); + sleep(Duration::from_millis(delay)); + + std::fs::remove_file(source_canonical).unwrap(); + sleep(Duration::from_millis(delay)); + + std::fs::copy(&backup, &source_canonical).unwrap(); + sleep(Duration::from_millis(delay)); + + p.kill().unwrap(); + + let mut buf_stdout = String::new(); + let mut p_stdout = p.stdout.take().unwrap(); + p_stdout.read_to_string(&mut buf_stdout).unwrap(); + assert_eq!(buf_stdout, expected_stdout); + + let mut buf_stderr = String::new(); + let mut p_stderr = p.stderr.take().unwrap(); + p_stderr.read_to_string(&mut buf_stderr).unwrap(); + assert_eq!(buf_stderr, expected_stderr); +} + #[test] fn test_follow_name_move() { // This test triggers a move event while `tail --follow=name logfile` is running. @@ -563,3 +608,46 @@ fn test_follow_name_move() { p_stderr.read_to_string(&mut buf_stderr).unwrap(); assert_eq!(buf_stderr, expected_stderr); } + +#[test] +fn test_follow_name_move_polling() { + // This test triggers a move event while `tail --follow=name --disable-inotify logfile` is running. + // mv logfile backup && sleep 1 && mv backup file + + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + + let source = FOLLOW_NAME_TXT; + let source_canonical = &at.plus(source); + let backup = at.plus_as_string("backup"); + + let expected_stdout = at.read("follow_name.expected"); + let expected_stderr = format!( + "{}: '{}' has been replaced; following new file\n", + ts.util_name, source + ); + + let args = ["--follow=name", "--disable-inotify", source]; + let mut p = ts.ucmd().args(&args).run_no_wait(); + + let delay = 750; + + sleep(Duration::from_millis(delay)); + std::fs::rename(&source_canonical, &backup).unwrap(); + sleep(Duration::from_millis(delay)); + + std::fs::rename(&backup, &source_canonical).unwrap(); + sleep(Duration::from_millis(delay)); + + p.kill().unwrap(); + + let mut buf_stdout = String::new(); + let mut p_stdout = p.stdout.take().unwrap(); + p_stdout.read_to_string(&mut buf_stdout).unwrap(); + assert_eq!(buf_stdout, expected_stdout); + + let mut buf_stderr = String::new(); + let mut p_stderr = p.stderr.take().unwrap(); + p_stderr.read_to_string(&mut buf_stderr).unwrap(); + assert_eq!(buf_stderr, expected_stderr); +}