use crate::store::write::writer::WriterCommand;
use crate::store::{Store, StoreError};
#[doc(hidden)]
impl Store {
pub fn panic_writer_for_test(&self) -> Result<(), StoreError> {
let (tx, rx) = flume::bounded(1);
self.state
.0
.tx
.send(WriterCommand::PanicForTest { respond: tx })
.map_err(|_| StoreError::WriterCrashed)?;
let _ = rx.recv_timeout(std::time::Duration::from_millis(500));
std::thread::sleep(std::time::Duration::from_millis(50));
Ok(())
}
}
#[cfg(all(test, feature = "dangerous-test-hooks"))]
mod tests {
use crate::coordinate::Coordinate;
use crate::event::EventKind;
use crate::store::{RestartPolicy, Store, StoreConfig, StoreError};
#[test]
fn panic_writer_for_test_really_crashes_the_writer() {
let dir = tempfile::tempdir().expect("tmpdir");
let config = StoreConfig::new(dir.path()).with_restart_policy(RestartPolicy::Once);
let store = Store::open(config).expect("open store");
let coord = Coordinate::new("entity:panic", "scope:panic").expect("coord");
let kind = EventKind::custom(0xF, 0x1);
store
.panic_writer_for_test()
.expect("send first panic command");
let _ = store.panic_writer_for_test();
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5);
let observed: Option<StoreError> = loop {
match store.append(&coord, kind, &serde_json::json!({ "n": 1 })) {
Err(e) => break Some(e),
Ok(_) if std::time::Instant::now() >= deadline => break None,
Ok(_) => std::thread::yield_now(),
}
};
let err = observed.expect(
"PROPERTY: after two panics under RestartPolicy::Once, append must fail — a no-op \
panic_writer_for_test would leave the writer alive and this append would succeed",
);
assert!(
matches!(err, StoreError::WriterCrashed),
"PROPERTY: append after an exhausted restart budget must surface WriterCrashed, got {err:?}"
);
}
}