119 lines
4.0 KiB
Rust
119 lines
4.0 KiB
Rust
use super::{APP, JOB, checked};
|
|
|
|
fn app(body: &str) -> String {
|
|
format!(
|
|
"{}\ntransaction send(key: Text) () {{ id = submit(key) }}\nlaunch() () {{ {body} }}",
|
|
APP
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn tasks_can_inherit_enqueue_identity_without_sharing_a_transaction() {
|
|
for body in [
|
|
"pending = run(send(\"one\"))\nwait(pending)\nsend(\"after\")",
|
|
"pool = group(2)\nrun(pool, send(\"one\"))\nrun(pool, send(\"two\"))\nwait(pool)\nsend(\"after\")",
|
|
"parallelEach(send, [\"one\", \"two\"], 2)\nsend(\"after\")",
|
|
] {
|
|
let source = app(body);
|
|
let program = checked(&source, JOB, "long cmd launch = app.launch").unwrap();
|
|
let signature = &program.functions[program.commands[0].function].signature;
|
|
assert!(signature.effects.enqueue);
|
|
assert!(!signature.effects.request);
|
|
assert!(!signature.effects.unscoped_write);
|
|
assert!(signature.effects.concurrent || signature.effects.parallel);
|
|
|
|
// 普通入口不能把自动事务变成多个独立提交;必须显式声明 long。
|
|
let error = checked(&source, JOB, "cmd launch = app.launch").unwrap_err();
|
|
assert_eq!(error.code, "C014", "{body}: {error:?}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn long_jobs_can_launch_children_only_through_explicit_transactions() {
|
|
let source = app("parallelEach(send, [\"one\", \"two\"], 2)");
|
|
let jobs = format!("{JOB}\nlong job fanout() () retry(1) timeout(1000) {{ app.launch() }}");
|
|
assert!(checked(&source, &jobs, "").is_ok());
|
|
assert_eq!(
|
|
checked(&source, &jobs.replace("long job", "job"), "")
|
|
.unwrap_err()
|
|
.code,
|
|
"C014"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn enqueue_does_not_escape_transaction_or_synchronous_worker_restrictions() {
|
|
for body in [
|
|
"pending = run(send(\"one\"))\nwait(pending)",
|
|
"pool = group(1)\nrun(pool, send(\"one\"))\nwait(pool)",
|
|
"parallelEach(send, [\"one\"], 1)",
|
|
] {
|
|
let source = app(body).replace("launch() ()", "transaction launch() ()");
|
|
assert_eq!(
|
|
checked(&source, JOB, "long cmd launch = app.launch")
|
|
.unwrap_err()
|
|
.code,
|
|
"C014",
|
|
"{body}"
|
|
);
|
|
}
|
|
for boundary in ["blocking", "parallel"] {
|
|
let source = app(&format!("{boundary}(send(\"one\"))"));
|
|
assert_eq!(
|
|
checked(&source, JOB, "long cmd launch = app.launch")
|
|
.unwrap_err()
|
|
.code,
|
|
"C013"
|
|
);
|
|
}
|
|
let unscoped =
|
|
app("pending = run(send(\"one\"))\nwait(pending)").replace("transaction send", "send");
|
|
assert_eq!(
|
|
checked(&unscoped, JOB, "long cmd launch = app.launch")
|
|
.unwrap_err()
|
|
.code,
|
|
"C014"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn public_enqueue_remains_forbidden_through_tasks() {
|
|
let source = app("pending = run(send(\"one\"))\nwait(pending)");
|
|
assert_eq!(
|
|
checked(&source, JOB, "public long post launch = app.launch")
|
|
.unwrap_err()
|
|
.code,
|
|
"C014"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn enqueue_capability_does_not_make_request_identity_transferable() {
|
|
for body in [
|
|
"pending = run(send(\"one\"))\nwait(pending)",
|
|
"pool = group(1)\nrun(pool, send(\"one\"))\nwait(pool)",
|
|
"parallelEach(send, [\"one\"], 1)",
|
|
] {
|
|
let source = app(body).replace(
|
|
"id = submit(key)",
|
|
"identity = dever.auth.id()\nid = submit(identity + key)",
|
|
);
|
|
let error = super::packages(&[
|
|
("dever.database", super::ERROR),
|
|
(
|
|
"dever.api",
|
|
"public type Error { error Invalid\nerror Unauthorized\nerror Forbidden }",
|
|
),
|
|
(
|
|
"dever.auth",
|
|
"public id() (value: Text) { value = dever.system.authId() }",
|
|
),
|
|
("demo.queue.app", &source),
|
|
("demo.queue.job", JOB),
|
|
("demo.queue.api", "long cmd launch = app.launch"),
|
|
])
|
|
.unwrap_err();
|
|
assert_eq!(error.code, "C013", "{body}: {error:?}");
|
|
}
|
|
}
|