mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-14 00:47:30 +00:00
Migrate uvar notifier test helper into its own module
Reduce the amount of stuff in mod.rs
This commit is contained in:
parent
a950a8270d
commit
acd0bf1a43
4 changed files with 91 additions and 90 deletions
|
@ -88,7 +88,7 @@ fn test_inotify_notifiers() {
|
|||
.iter()
|
||||
.map(|n| n as &dyn UniversalNotifier)
|
||||
.collect::<Vec<_>>();
|
||||
super::test_notifiers(¬ifiers, Some(&fake_uvars_path));
|
||||
super::test_helpers::test_notifiers(¬ifiers, Some(&fake_uvars_path));
|
||||
|
||||
let _ = remove_dir_all(PathBuf::from(wcs2osstring(&fake_uvars_dir)));
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@ mod notifyd;
|
|||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
mod inotify;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_helpers;
|
||||
|
||||
/// The "universal notifier" is an object responsible for broadcasting and receiving universal
|
||||
/// variable change notifications. These notifications do not contain the change, but merely
|
||||
/// indicate that the uvar file has changed. It is up to the uvar subsystem to re-read the file.
|
||||
|
@ -68,91 +71,3 @@ static DEFAULT_NOTIFIER: OnceCell<Box<dyn UniversalNotifier>> = OnceCell::new();
|
|||
pub fn default_notifier() -> &'static dyn UniversalNotifier {
|
||||
DEFAULT_NOTIFIER.get_or_init(create_notifier).as_ref()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::wchar::prelude::*;
|
||||
|
||||
// Test a slice of notifiers.
|
||||
// fish_variables_path is the path to the (simulated) fish_variables file.
|
||||
#[cfg(test)]
|
||||
pub fn test_notifiers(notifiers: &[&dyn UniversalNotifier], fish_variables_path: Option<&wstr>) {
|
||||
let poll_notifier = |n: &dyn UniversalNotifier| -> bool {
|
||||
let Some(fd) = n.notification_fd() else {
|
||||
return false;
|
||||
};
|
||||
if crate::fd_readable_set::poll_fd_readable(fd) {
|
||||
n.notification_fd_became_readable(fd)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
// Helper to simulate modifying a file, using the atomic rename() approach.
|
||||
let modify_path = |path: &wstr| -> Result<(), std::io::Error> {
|
||||
use crate::common::wcs2osstring;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
let path = wcs2osstring(path);
|
||||
let mut new_path = std::path::PathBuf::from(path.clone());
|
||||
new_path.set_extension("new");
|
||||
|
||||
let mut file = fs::File::create(&new_path)?;
|
||||
file.write_all(b"Random text")?;
|
||||
std::mem::drop(file);
|
||||
fs::rename(new_path, path)?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// Nobody should poll yet.
|
||||
for (idx, &n) in notifiers.iter().enumerate() {
|
||||
assert!(
|
||||
!poll_notifier(n),
|
||||
"notifier {} polled before notification",
|
||||
idx
|
||||
);
|
||||
}
|
||||
|
||||
// Tweak each notifier. Verify that others see it.
|
||||
for (idx1, &n1) in notifiers.iter().enumerate() {
|
||||
n1.post_notification();
|
||||
|
||||
// If we're using inotify, simulate modifying the file.
|
||||
if let Some(path) = fish_variables_path {
|
||||
modify_path(path).expect("failed to modify file");
|
||||
}
|
||||
|
||||
// notifyd requires a round trip to the notifyd server, which means we have to wait a
|
||||
// little bit to receive it. In practice 40 ms seems to be enough.
|
||||
unsafe { libc::usleep(40000) };
|
||||
|
||||
for (idx2, &n2) in notifiers.iter().enumerate() {
|
||||
let mut polled = poll_notifier(n2);
|
||||
|
||||
// We aren't concerned with the one who posted, except we do need to poll to drain it.
|
||||
if idx1 == idx2 {
|
||||
continue;
|
||||
}
|
||||
assert!(
|
||||
polled,
|
||||
"notifier {} did not see notification from {}",
|
||||
idx2, idx1
|
||||
);
|
||||
// It should not poll again immediately.
|
||||
polled = poll_notifier(n2);
|
||||
assert!(
|
||||
!polled,
|
||||
"notifier {} polled twice after notification from {}",
|
||||
idx2, idx1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Nobody should poll now.
|
||||
for (idx, &n) in notifiers.iter().enumerate() {
|
||||
assert!(
|
||||
!poll_notifier(n),
|
||||
"notifier {} polled after all changes",
|
||||
idx
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,5 +145,5 @@ fn test_notifyd_notifiers() {
|
|||
.iter()
|
||||
.map(|n| n as &dyn UniversalNotifier)
|
||||
.collect::<Vec<_>>();
|
||||
super::test_notifiers(¬ifiers, None);
|
||||
super::test_helpers::test_notifiers(¬ifiers, None);
|
||||
}
|
||||
|
|
86
fish-rust/src/universal_notifier/test_helpers.rs
Normal file
86
fish-rust/src/universal_notifier/test_helpers.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
use super::UniversalNotifier;
|
||||
use crate::wchar::prelude::*;
|
||||
|
||||
// Helper to test a slice of notifiers.
|
||||
// fish_variables_path is the path to the (simulated) fish_variables file, if using the inotify notifier.
|
||||
pub fn test_notifiers(notifiers: &[&dyn UniversalNotifier], fish_variables_path: Option<&wstr>) {
|
||||
let poll_notifier = |n: &dyn UniversalNotifier| -> bool {
|
||||
let Some(fd) = n.notification_fd() else {
|
||||
return false;
|
||||
};
|
||||
if crate::fd_readable_set::poll_fd_readable(fd) {
|
||||
n.notification_fd_became_readable(fd)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
// Helper to simulate modifying a file, using the atomic rename() approach.
|
||||
let modify_path = |path: &wstr| -> Result<(), std::io::Error> {
|
||||
use crate::common::wcs2osstring;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
let path = wcs2osstring(path);
|
||||
let mut new_path = std::path::PathBuf::from(path.clone());
|
||||
new_path.set_extension("new");
|
||||
|
||||
let mut file = fs::File::create(&new_path)?;
|
||||
file.write_all(b"Random text")?;
|
||||
std::mem::drop(file);
|
||||
fs::rename(new_path, path)?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// Nobody should poll yet.
|
||||
for (idx, &n) in notifiers.iter().enumerate() {
|
||||
assert!(
|
||||
!poll_notifier(n),
|
||||
"notifier {} polled before notification",
|
||||
idx
|
||||
);
|
||||
}
|
||||
|
||||
// Tweak each notifier. Verify that others see it.
|
||||
for (idx1, &n1) in notifiers.iter().enumerate() {
|
||||
n1.post_notification();
|
||||
|
||||
// If we're using inotify, simulate modifying the file.
|
||||
if let Some(path) = fish_variables_path {
|
||||
modify_path(path).expect("failed to modify file");
|
||||
}
|
||||
|
||||
// notifyd requires a round trip to the notifyd server, which means we have to wait a
|
||||
// little bit to receive it. In practice 40 ms seems to be enough.
|
||||
unsafe { libc::usleep(40000) };
|
||||
|
||||
for (idx2, &n2) in notifiers.iter().enumerate() {
|
||||
let mut polled = poll_notifier(n2);
|
||||
|
||||
// We aren't concerned with the one who posted, except we do need to poll to drain it.
|
||||
if idx1 == idx2 {
|
||||
continue;
|
||||
}
|
||||
assert!(
|
||||
polled,
|
||||
"notifier {} did not see notification from {}",
|
||||
idx2, idx1
|
||||
);
|
||||
// It should not poll again immediately.
|
||||
polled = poll_notifier(n2);
|
||||
assert!(
|
||||
!polled,
|
||||
"notifier {} polled twice after notification from {}",
|
||||
idx2, idx1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Nobody should poll now.
|
||||
for (idx, &n) in notifiers.iter().enumerate() {
|
||||
assert!(
|
||||
!poll_notifier(n),
|
||||
"notifier {} polled after all changes",
|
||||
idx
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue