sim-kernel 0.1.0-rc.1

SIM workspace package for sim kernel.
Documentation
use crate::{
    CapabilityName, Consistency, Cx, Diagnostic, EvalFabric, EvalMode, EvalReply, EvalRequest,
    EventKind, EventSource, Expr, ObserveMode, RealizeRequest, Result, Value, realize_events,
    realize_final,
};

#[derive(Clone)]
struct StaticFabric {
    reply: EvalReply,
}

impl EvalFabric for StaticFabric {
    fn realize(&self, _cx: &mut Cx, _request: EvalRequest) -> Result<EvalReply> {
        Ok(self.reply.clone())
    }
}

fn request(expr: Expr) -> EvalRequest {
    EvalRequest {
        expr,
        result_shape: None,
        required_capabilities: Vec::new(),
        deadline: None,
        consistency: Consistency::LocalFirst,
        mode: EvalMode::Eval,
        answer_limit: None,
        stream_buffer: None,
        stream: false,
        trace: false,
    }
}

fn reply(value: Value) -> EvalReply {
    EvalReply {
        value,
        diagnostics: Vec::new(),
        trace: None,
    }
}

#[test]
fn eventful_realize_source_drains_to_final_then_done() {
    let mut cx = Cx::stub();
    let value = cx.factory().string("ok".to_owned()).unwrap();
    let fabric = StaticFabric {
        reply: reply(value.clone()),
    };

    let source = realize_events(&mut cx, &fabric, request(Expr::String("task".to_owned())))
        .expect("event source");
    let mut kinds = Vec::new();
    while let Some(event) = source.next(&mut cx).unwrap() {
        kinds.push(event.kind);
    }

    assert!(matches!(kinds.first(), Some(EventKind::Started { .. })));
    assert!(matches!(
        kinds.get(kinds.len().saturating_sub(2)),
        Some(EventKind::Final(_))
    ));
    assert!(matches!(kinds.last(), Some(EventKind::Done)));
}

#[test]
fn eventful_realize_drains_back_to_eval_reply() {
    let mut cx = Cx::stub();
    let value = cx.factory().string("final".to_owned()).unwrap();
    let fabric = StaticFabric {
        reply: reply(value.clone()),
    };

    let drained = realize_final(&mut cx, &fabric, request(Expr::Nil)).unwrap();

    assert_eq!(drained.value, value);
    assert!(drained.diagnostics.is_empty());
    assert!(drained.trace.is_none());
}

#[test]
fn diagnostics_survive_eventful_realize() {
    let mut cx = Cx::stub();
    let value = cx.factory().nil().unwrap();
    let diagnostic = Diagnostic::info("kept");
    let fabric = StaticFabric {
        reply: EvalReply {
            value,
            diagnostics: vec![diagnostic.clone()],
            trace: None,
        },
    };

    let drained = realize_final(&mut cx, &fabric, request(Expr::Nil)).unwrap();

    assert_eq!(drained.diagnostics, vec![diagnostic]);
}

#[test]
fn trace_survives_eventful_realize() {
    let mut cx = Cx::stub();
    let value = cx.factory().nil().unwrap();
    let trace = cx.factory().string("trace".to_owned()).unwrap();
    let fabric = StaticFabric {
        reply: EvalReply {
            value,
            diagnostics: Vec::new(),
            trace: Some(trace.clone()),
        },
    };

    let drained = realize_final(&mut cx, &fabric, request(Expr::Nil)).unwrap();

    assert_eq!(drained.trace, Some(trace));
}

#[test]
fn old_eval_request_observation_flags_map_to_realize_request() {
    let mut cx = Cx::stub();
    let mut streaming = request(Expr::Nil);
    streaming.stream = true;
    streaming.trace = true;
    streaming.stream_buffer = Some(8);
    streaming.required_capabilities = vec![CapabilityName::new("demo")];

    let eventful = RealizeRequest::from_eval_request(&mut cx, &streaming).unwrap();
    let back = eventful.to_eval_request(&mut cx).unwrap();

    assert_eq!(eventful.observe, ObserveMode::Events);
    assert_eq!(eventful.buffer_limit, Some(8));
    assert_eq!(
        eventful.required_capabilities,
        vec![CapabilityName::new("demo")]
    );
    assert!(back.stream);
    assert!(back.trace);
    assert_eq!(back.stream_buffer, Some(8));
}