mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-15 06:24:01 +00:00
77 lines
2.4 KiB
Rust
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();
|
|
}
|
|
}
|