use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use crate::context::ComponentContext;
pub trait ComponentExecutor: Send + Sync {
fn set_context(&mut self, context: Box<dyn ComponentContext>);
fn ccm_activate(&mut self) -> Result<(), CifError> {
Ok(())
}
fn ccm_passivate(&mut self) -> Result<(), CifError> {
Ok(())
}
fn ccm_remove(&mut self) -> Result<(), CifError> {
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CifError {
CcmException(String),
}
pub trait SessionExecutor: ComponentExecutor {
fn session_marker(&self) {}
}
pub trait KeyedExecutor: ComponentExecutor {
fn primary_key(&self) -> Vec<u8>;
}
pub trait ExecutorLocator: Send + Sync {
fn obtain_executor(&self, oid: &[u8]) -> Result<Box<dyn ComponentExecutor>, CifError>;
}
#[cfg(test)]
#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
mod tests {
use super::*;
use core::sync::atomic::{AtomicUsize, Ordering};
struct LoggingContext {
log: alloc::sync::Arc<AtomicUsize>,
}
impl ComponentContext for LoggingContext {
fn get_caller_principal(&self) -> Option<alloc::vec::Vec<u8>> {
self.log.fetch_add(1, Ordering::Relaxed);
None
}
}
struct DemoExecutor {
ctx: Option<Box<dyn ComponentContext>>,
activations: AtomicUsize,
passivations: AtomicUsize,
}
impl ComponentExecutor for DemoExecutor {
fn set_context(&mut self, c: Box<dyn ComponentContext>) {
self.ctx = Some(c);
}
fn ccm_activate(&mut self) -> Result<(), CifError> {
self.activations.fetch_add(1, Ordering::Relaxed);
Ok(())
}
fn ccm_passivate(&mut self) -> Result<(), CifError> {
self.passivations.fetch_add(1, Ordering::Relaxed);
Ok(())
}
}
impl SessionExecutor for DemoExecutor {}
#[test]
fn lifecycle_calls_increment_counters() {
let mut e = DemoExecutor {
ctx: None,
activations: AtomicUsize::new(0),
passivations: AtomicUsize::new(0),
};
e.set_context(Box::new(LoggingContext {
log: alloc::sync::Arc::new(AtomicUsize::new(0)),
}));
assert!(e.ctx.is_some());
e.ccm_activate().unwrap();
e.ccm_activate().unwrap();
e.ccm_passivate().unwrap();
assert_eq!(e.activations.load(Ordering::Relaxed), 2);
assert_eq!(e.passivations.load(Ordering::Relaxed), 1);
}
#[test]
fn cif_error_carries_diagnostic() {
let e = CifError::CcmException("permission denied".into());
match e {
CifError::CcmException(s) => assert_eq!(s, "permission denied"),
}
}
}