use std::time::Duration;
use thal::runtime::Molecule;
use thal::value::Value;
use thal::Reactor;
const PROGRAM: &str = r#"
molecule Source {
id: Int
primary_key: id
}
molecule TaskA {
src_id: Int
note: String?
primary_key: src_id
}
molecule TaskB {
src_id: Int
primary_key: src_id
}
molecule TaskC {
src_id: Int
primary_key: src_id
}
reaction Fanout {
when: Source(s)
emit:
TaskA { src_id: s.id, note: null },
TaskB { src_id: s.id },
TaskC { src_id: s.id }
}
"#;
#[tokio::test(flavor = "multi_thread")]
async fn fanout_emits_three_kinds_with_optional_field() {
let program = thal::load_str(PROGRAM).expect("load");
let reactor = Reactor::new(program);
let store = reactor.store();
let handle = reactor.handle();
let task = tokio::spawn(reactor.run());
handle
.emit(
Molecule::builder("Source")
.field("id", Value::Int(1))
.build(),
)
.await
.expect("emit Source");
tokio::time::sleep(Duration::from_millis(100)).await;
task.abort();
let task_a = store.scan_by_name("TaskA");
let task_b = store.scan_by_name("TaskB");
let task_c = store.scan_by_name("TaskC");
assert_eq!(task_a.len(), 1, "expected one TaskA, got {}", task_a.len());
assert_eq!(task_b.len(), 1, "expected one TaskB, got {}", task_b.len());
assert_eq!(task_c.len(), 1, "expected one TaskC, got {}", task_c.len());
assert_eq!(task_a[0].fields["src_id"], Value::Int(1));
assert_eq!(
task_a[0].fields["note"],
Value::Null,
"null literal should round-trip through the store as Value::Null"
);
assert_eq!(task_b[0].fields["src_id"], Value::Int(1));
assert_eq!(task_c[0].fields["src_id"], Value::Int(1));
}