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));
}