use sim_kernel::{CapabilityName, Cx, GrantSeat};
use crate::OfficeError;
pub const NET_CONNECT_CAPABILITY: &str = "net-connect";
pub const PROCESS_SPAWN_CAPABILITY: &str = "process-spawn";
pub const WALL_CLOCK_CAPABILITY: &str = "wall-clock";
pub const CREDENTIALS_CAPABILITY: &str = "credentials";
pub struct OfficeCapabilityProfile;
macro_rules! grant_into_result {
($grant:expr) => {{
#[allow(clippy::let_unit_value)]
let grant_result = $grant;
#[allow(clippy::unit_arg)]
grant_result.into_result()
}};
}
impl OfficeCapabilityProfile {
#[must_use]
pub fn granted() -> Vec<CapabilityName> {
Vec::new()
}
#[must_use]
pub fn denied() -> Vec<CapabilityName> {
[
NET_CONNECT_CAPABILITY,
PROCESS_SPAWN_CAPABILITY,
WALL_CLOCK_CAPABILITY,
CREDENTIALS_CAPABILITY,
]
.into_iter()
.map(CapabilityName::new)
.collect()
}
pub fn seat(seat: &GrantSeat, cx: &mut Cx) -> Result<(), OfficeError> {
for capability in Self::granted() {
grant_into_result!(seat.grant(cx, capability))?;
}
Ok(())
}
}
trait GrantOutcome {
fn into_result(self) -> Result<(), OfficeError>;
}
impl GrantOutcome for () {
fn into_result(self) -> Result<(), OfficeError> {
Ok(())
}
}
impl GrantOutcome for sim_kernel::Result<()> {
fn into_result(self) -> Result<(), OfficeError> {
self.map_err(OfficeError::from)
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use sim_kernel::{DefaultFactory, NoopEvalPolicy};
use super::*;
#[test]
fn default_profile_denies_live_capabilities() {
let denied: Vec<_> = OfficeCapabilityProfile::denied()
.into_iter()
.map(|capability| capability.as_str().to_owned())
.collect();
assert_eq!(
denied,
vec![
NET_CONNECT_CAPABILITY,
PROCESS_SPAWN_CAPABILITY,
WALL_CLOCK_CAPABILITY,
CREDENTIALS_CAPABILITY,
]
);
assert!(OfficeCapabilityProfile::granted().is_empty());
}
#[test]
fn seating_default_profile_does_not_grant_live_network() {
let (mut cx, seat) = sim_kernel::Cx::new_seated(
Arc::new(NoopEvalPolicy),
Arc::new(DefaultFactory),
sim_kernel::HandleSeed::new(0xce27_937d_0a0a_e3ea),
);
OfficeCapabilityProfile::seat(&seat, &mut cx).unwrap();
let network = CapabilityName::new(NET_CONNECT_CAPABILITY);
assert!(cx.require(&network).is_err());
}
}