#![cfg(feature = "tensor")]
use dataflow_rs::Engine;
use dataflow_rs::engine::message::Message;
use serde_json::json;
mod common;
use common::workflow;
async fn run(logic: serde_json::Value) -> Message {
let engine = Engine::builder()
.with_workflow(workflow(json!({
"id": "w", "name": "w", "priority": 0,
"tasks": [
{ "id": "t", "name": "t", "function": {
"name": "map",
"input": { "mappings": [ { "path": "data.out", "logic": logic } ] } } }
]
})))
.build()
.unwrap();
let mut m = Message::from_value(&json!({}));
engine.process_message(&mut m).await.unwrap();
m
}
fn out(m: &Message) -> serde_json::Value {
serde_json::Value::from(m.data().get("out").unwrap())
}
#[tokio::test]
async fn a_tensor_operator_evaluates_inside_a_workflow() {
let m = run(json!({
"to_list": [ { "cast": [ { "tensor": [[1.7, 300, -5], "f64"] }, "u8" ] } ]
}))
.await;
assert!(m.errors().is_empty(), "{:?}", m.errors());
assert_eq!(
out(&m),
json!([1, 255, 0]),
"narrowing should saturate, not wrap"
);
}
#[tokio::test]
async fn a_tensor_survives_the_owned_value_boundary() {
let m = run(json!({ "tensor": [[1, 2, 3], "u8"] })).await;
assert!(m.errors().is_empty(), "{:?}", m.errors());
let value = out(&m);
assert!(
!value.is_null(),
"a tensor must not flatten to null crossing OwnedDataValue: {value}"
);
}
#[tokio::test]
async fn shape_is_a_live_operator_once_the_feature_is_on() {
let m = run(json!({ "shape": [ { "tensor": [[1, 2, 3], "u8"] } ] })).await;
assert_eq!(
out(&m),
json!([3]),
"`shape` should have evaluated, not echoed back as data"
);
let escaped = run(json!({ "$shape": [1, 2, 3] })).await;
assert_eq!(
out(&escaped),
json!({ "shape": [1, 2, 3] }),
"the `$` escape must still pin the literal reading"
);
}