feat: update library lifecycle return value

This commit is contained in:
2026-08-10 22:17:19 +08:00
parent 65e825f8db
commit 44adb10989
2 changed files with 61 additions and 42 deletions
+46 -32
View File
@@ -16,24 +16,28 @@ struct State {
}
/// Coverage: a single paired startup/shutdown runs init once and destroy once, destroy receives the
/// state produced by init, and the count returns to zero.
/// state produced by init, both report that they ran the closure, and the count returns to zero.
#[test]
fn paired_startup_shutdown() {
let inits = AtomicUsize::new(0);
let destroys = AtomicUsize::new(0);
let lc: LibraryLifecycle<State> = LibraryLifecycle::new();
lc.startup(|| -> Result<State, TestErr> {
inits.fetch_add(1, Ordering::SeqCst);
Ok(State { value: 42 })
})
.unwrap();
let ran_init = lc
.startup(|| -> Result<State, TestErr> {
inits.fetch_add(1, Ordering::SeqCst);
Ok(State { value: 42 })
})
.unwrap();
assert!(ran_init);
lc.shutdown(|s| {
destroys.fetch_add(1, Ordering::SeqCst);
assert_eq!(s.value, 42);
})
.unwrap();
let ran_destroy = lc
.shutdown(|s| {
destroys.fetch_add(1, Ordering::SeqCst);
assert_eq!(s.value, 42);
})
.unwrap();
assert!(ran_destroy);
assert_eq!(inits.load(Ordering::SeqCst), 1);
assert_eq!(destroys.load(Ordering::SeqCst), 1);
@@ -42,29 +46,35 @@ fn paired_startup_shutdown() {
/// Coverage: multiple startups followed by matching shutdowns run init and destroy only on the
/// boundary transitions (once each); the init/destroy closures passed on non-transition calls are
/// dropped without being run.
/// dropped without being run, and the bool return reflects exactly which calls ran a closure.
#[test]
fn multiple_startups_shutdowns_run_only_on_boundaries() {
let inits = AtomicUsize::new(0);
let destroys = AtomicUsize::new(0);
let lc: LibraryLifecycle<State> = LibraryLifecycle::new();
for _ in 0..3 {
lc.startup(|| -> Result<State, TestErr> {
inits.fetch_add(1, Ordering::SeqCst);
Ok(State { value: 7 })
let startup_ran: Vec<bool> = (0..3)
.map(|_| {
lc.startup(|| -> Result<State, TestErr> {
inits.fetch_add(1, Ordering::SeqCst);
Ok(State { value: 7 })
})
.unwrap()
})
.unwrap();
}
.collect();
assert_eq!(startup_ran, vec![true, false, false]);
assert_eq!(lc.count(), 3);
assert_eq!(inits.load(Ordering::SeqCst), 1);
for _ in 0..3 {
lc.shutdown(|_s| {
destroys.fetch_add(1, Ordering::SeqCst);
let shutdown_ran: Vec<bool> = (0..3)
.map(|_| {
lc.shutdown(|_s| {
destroys.fetch_add(1, Ordering::SeqCst);
})
.unwrap()
})
.unwrap();
}
.collect();
assert_eq!(shutdown_ran, vec![false, false, true]);
assert_eq!(inits.load(Ordering::SeqCst), 1);
assert_eq!(destroys.load(Ordering::SeqCst), 1);
@@ -79,15 +89,19 @@ fn reinitialization_runs_init_and_destroy_again() {
let lc: LibraryLifecycle<State> = LibraryLifecycle::new();
for _ in 0..2 {
lc.startup(|| -> Result<State, TestErr> {
inits.fetch_add(1, Ordering::SeqCst);
Ok(State { value: 1 })
})
.unwrap();
lc.shutdown(|_s| {
destroys.fetch_add(1, Ordering::SeqCst);
})
.unwrap();
let ran_init = lc
.startup(|| -> Result<State, TestErr> {
inits.fetch_add(1, Ordering::SeqCst);
Ok(State { value: 1 })
})
.unwrap();
assert!(ran_init);
let ran_destroy = lc
.shutdown(|_s| {
destroys.fetch_add(1, Ordering::SeqCst);
})
.unwrap();
assert!(ran_destroy);
}
assert_eq!(inits.load(Ordering::SeqCst), 2);