Phase 7.3 strangler reorg — rename the native widget host and the desktop runner crates to the op- prefix. The desktop+native merge was declined: keeping the library / binary split preserves the mobile- checkable op-host-native lib (cargo check -p op-host-native on iOS / Android, relied on by check-jian-boundaries.sh + the CI mobile job), which a folded-in winit binary would break. A clean separate rename is purely mechanical and the brief permits it. - openpencil-shell-native -> op-host-native (lib op_host_native) - openpencil-desktop -> op-host-desktop crate; the shipped executable keeps the stable openpencil-desktop [[bin]] name so release artifacts + external CLI integrations are unaffected - every openpencil_shell_core:: path -> op_editor_ui:: - every openpencil_shell_native:: path -> op_host_native:: - doc-comment / manual-smoke note refs updated
46 lines
1.6 KiB
Rust
46 lines
1.6 KiB
Rust
//! Spec v19 §3.3 / plan v7 Task 2 Step 16a:
|
|
//! `teardown` + lifecycle hooks must be idempotent.
|
|
//!
|
|
//! Three repeated calls of every hook (and `teardown`) must complete
|
|
//! without panic. Acceptance #6 covers this for the post-loop case;
|
|
//! this test pins the structural invariant on the empty-context
|
|
//! branch (the hardest path to get wrong is "already-`None` fields
|
|
//! shouldn't blow up").
|
|
|
|
mod common;
|
|
|
|
use common::setup_headless_context;
|
|
|
|
#[test]
|
|
fn teardown_three_times_no_panic() {
|
|
let mut ctx = setup_headless_context();
|
|
ctx.teardown().expect("first teardown");
|
|
ctx.teardown().expect("second teardown");
|
|
ctx.teardown().expect("third teardown");
|
|
}
|
|
|
|
#[test]
|
|
fn lifecycle_hooks_are_idempotent() {
|
|
// Mirrors spec §11.4 invariant + plan v7 Task 2 Step 16a:
|
|
// on_pause/on_resume/on_low_memory/teardown must each survive
|
|
// back-to-back invocation without panic.
|
|
let mut ctx = setup_headless_context();
|
|
ctx.on_pause().expect("on_pause #1");
|
|
ctx.on_pause().expect("on_pause #2");
|
|
ctx.on_resume(None).expect("on_resume #1");
|
|
ctx.on_resume(None).expect("on_resume #2");
|
|
ctx.on_low_memory();
|
|
ctx.on_low_memory();
|
|
ctx.teardown().expect("teardown #1");
|
|
ctx.teardown().expect("teardown #2");
|
|
}
|
|
|
|
#[test]
|
|
fn drop_after_teardown_is_safe() {
|
|
// Drop's `teardown` fallback must coexist with explicit teardown
|
|
// without double-free / panic (matches spec §3.3 Drop impl).
|
|
let mut ctx = setup_headless_context();
|
|
ctx.teardown().expect("explicit teardown");
|
|
drop(ctx); // implicit teardown — must be no-op
|
|
}
|