fish-shell/src/tests/topic_monitor.rs

77 lines
2.4 KiB
Rust

use crate::tests::prelude::*;
use crate::topic_monitor::{GenerationsList, Topic, TopicMonitor};
use std::sync::{
atomic::{AtomicU32, AtomicU64, Ordering},
Arc,
};
#[test]
#[serial]
fn test_topic_monitor() {
let _cleanup = test_init();
let monitor = TopicMonitor::default();
let gens = GenerationsList::new();
let t = Topic::sigchld;
gens.sigchld.set(0);
assert_eq!(monitor.generation_for_topic(t), 0);
let changed = monitor.check(&gens, false /* wait */);
assert!(!changed);
assert_eq!(gens.sigchld.get(), 0);
monitor.post(t);
let changed = monitor.check(&gens, true /* wait */);
assert!(changed);
assert_eq!(gens.get(t), 1);
assert_eq!(monitor.generation_for_topic(t), 1);
monitor.post(t);
assert_eq!(monitor.generation_for_topic(t), 2);
let changed = monitor.check(&gens, true /* wait */);
assert!(changed);
assert_eq!(gens.sigchld.get(), 2);
}
#[test]
#[serial]
fn test_topic_monitor_torture() {
let _cleanup = test_init();
let monitor = Arc::new(TopicMonitor::default());
const THREAD_COUNT: usize = 64;
let t1 = Topic::sigchld;
let t2 = Topic::sighupint;
let mut gens_list = vec![GenerationsList::invalid(); THREAD_COUNT];
let post_count = Arc::new(AtomicU64::new(0));
for gen in &mut gens_list {
*gen = monitor.current_generations();
post_count.fetch_add(1, Ordering::Relaxed);
monitor.post(t1);
}
let completed = Arc::new(AtomicU32::new(0));
let mut threads = vec![];
for gens in gens_list {
let monitor = Arc::downgrade(&monitor);
let post_count = Arc::downgrade(&post_count);
let completed = Arc::downgrade(&completed);
threads.push(std::thread::spawn(move || {
for _ in 0..1 << 11 {
let before = gens.clone();
let _changed = monitor.upgrade().unwrap().check(&gens, true /* wait */);
assert!(before.get(t1) < gens.get(t1));
assert!(gens.get(t1) <= post_count.upgrade().unwrap().load(Ordering::Relaxed));
assert_eq!(gens.get(t2), 0);
}
let _amt = completed.upgrade().unwrap().fetch_add(1, Ordering::Relaxed);
}));
}
while completed.load(Ordering::Relaxed) < THREAD_COUNT.try_into().unwrap() {
post_count.fetch_add(1, Ordering::Relaxed);
monitor.post(t1);
std::thread::yield_now();
}
for t in threads {
t.join().unwrap();
}
}