optative-derive 0.0.1

Procedural macros for the optative reconciler library: #[lifecycle_trace] and #[derive(Ephemeral)].
Documentation
use optative::{Lifecycle, OptativeSet, Reconcile};
use optative_derive::lifecycle_trace;

struct TraceSpec {
    id: String,
}

impl std::fmt::Display for TraceSpec {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.id)
    }
}

#[lifecycle_trace]
impl Lifecycle for TraceSpec {
    type Key = String;
    type State = ();
    type Context = ();
    type Output = ();
    type Error = std::convert::Infallible;

    fn key(&self) -> String {
        self.id.clone()
    }

    fn enter(self, _ctx: &mut (), _output: &mut ()) -> Result<(), Self::Error> {
        Ok(())
    }

    fn reconcile_self(
        self,
        _state: &mut (),
        _ctx: &mut (),
        _output: &mut (),
    ) -> Result<(), Self::Error> {
        Ok(())
    }

    fn exit(_state: (), _ctx: &mut (), _output: &mut Self::Output) -> Result<(), Self::Error> {
        Ok(())
    }

    fn display_name(&self) -> String {
        self.id.clone()
    }
}

#[test]
#[tracing_test::traced_test]
fn entering_emits_info_event_with_key_name() {
    let mut set: OptativeSet<TraceSpec> = OptativeSet::new();
    set.reconcile(
        vec![TraceSpec {
            id: "trace-panel".to_string(),
        }],
        &mut (),
        &mut (),
    );
    assert!(logs_contain("entering"), "expected an 'entering' log entry");
    assert!(
        logs_contain("trace-panel"),
        "expected key/name 'trace-panel' in log"
    );
}

#[test]
#[tracing_test::traced_test]
fn exiting_emits_info_event_when_removed_from_desired_set() {
    let mut set: OptativeSet<TraceSpec> = OptativeSet::new();
    set.reconcile(
        vec![TraceSpec {
            id: "leaving".to_string(),
        }],
        &mut (),
        &mut (),
    );
    set.reconcile(vec![], &mut (), &mut ());
    assert!(logs_contain("exiting"), "expected an 'exiting' log entry");
}