117 lines
4.2 KiB
Rust
117 lines
4.2 KiB
Rust
use super::linked;
|
|
|
|
#[test]
|
|
fn selection_checks_named_outputs_static_fallback_and_affine_ownership() {
|
|
let prefix = "work() (value: Int) { value = 1 }\nfallback() (value: Int) { value = 2 }\n";
|
|
for body in [
|
|
"value = timeout(run(work()), 1, fallback)",
|
|
"first = run(work())\n second = run(work())\n value = race(first, second)",
|
|
] {
|
|
assert!(linked(&format!("{prefix}main() (value: Int) {{ {body} }}")).is_ok());
|
|
}
|
|
for (extra, body, code) in [
|
|
(
|
|
"wrong() (answer: Int) { answer = 0 }",
|
|
"value = timeout(run(work()), 1, wrong)",
|
|
"C005",
|
|
),
|
|
(
|
|
"wrong(input: Int) (value: Int) { value = input }",
|
|
"value = timeout(run(work()), 1, wrong)",
|
|
"C005",
|
|
),
|
|
(
|
|
"wrong() (answer: Int) { answer = 0 }",
|
|
"value = race(run(work()), run(wrong()))",
|
|
"C005",
|
|
),
|
|
("", "value = race(run(work()))", "C005"),
|
|
("", "value = race(run(work()), 1)", "C005"),
|
|
(
|
|
"",
|
|
"pending = run(work())\n value = race(pending, pending)",
|
|
"C013",
|
|
),
|
|
(
|
|
"",
|
|
"pending = run(work())\n value = timeout(pending, 1, fallback)\n again = wait(pending)",
|
|
"C013",
|
|
),
|
|
("", "value = timeout(run(work()), 1.0e0, fallback)", "C005"),
|
|
] {
|
|
let source = format!("{prefix}{extra}\nmain() (value: Int) {{ {body} }}");
|
|
assert_eq!(linked(&source).unwrap_err().code, code, "{source}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn timeout_retains_task_ownership_while_duration_is_awaited() {
|
|
let source = "work() (value: Int) { value = 1 }\nfallback() (value: Int) { value = 2 }\nduration() (value: Int) { dever.task.sleep(0)\n value = 1 }\nmain() (value: Int) { value = timeout(run(work()), duration(), fallback) }";
|
|
assert!(linked(source).is_ok());
|
|
assert_eq!(linked("work() () {}\nfallback() () { dever.io.println(\"blocked\") }\nmain() () { timeout(run(work()), 1, fallback) }").unwrap_err().code, "C013");
|
|
}
|
|
|
|
#[test]
|
|
fn cancellation_does_not_discharge_input_error_obligations() {
|
|
let prefix = "type Result { Done\n error Failed(message: Text) }\nhandle(value: Result) () recover(\"handles input\") {}\nempty() () {}\n";
|
|
for body in [
|
|
"timeout(run(handle(Result.Failed(\"first\"))), 1, empty)",
|
|
"race(run(handle(Result.Failed(\"first\"))), run(handle(Result.Failed(\"second\"))))",
|
|
"problem = Result.Failed(\"shared\")\n race(run(handle(problem)), run(empty()))",
|
|
] {
|
|
assert_eq!(
|
|
linked(&format!("{prefix}main() () {{ {body} }}"))
|
|
.unwrap_err()
|
|
.code,
|
|
"C012"
|
|
);
|
|
}
|
|
assert!(linked(&format!("{prefix}main() () {{ problem = Result.Failed(\"shared\")\n race(run(handle(problem)), run(handle(problem))) }}")).is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn selected_error_values_must_be_returned_or_handled() {
|
|
let prefix = "type Result { Done(value: Int)\n error Failed(message: Text) }\nwork() (value: Result) { value = Result.Failed(\"reason\") }\nfallback() (value: Result) { value = Result.Done(0) }\n";
|
|
for operation in [
|
|
"timeout(run(work()), 1, fallback)",
|
|
"race(run(work()), run(work()))",
|
|
] {
|
|
assert_eq!(
|
|
linked(&format!("{prefix}main() () {{ lost = {operation} }}"))
|
|
.unwrap_err()
|
|
.code,
|
|
"C012"
|
|
);
|
|
assert!(
|
|
linked(&format!(
|
|
"{prefix}main() (value: Result) {{ value = {operation} }}"
|
|
))
|
|
.is_ok()
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn selected_ranges_include_fallback_and_each_possible_winner() {
|
|
let prefix = "one() (value: Int) { value = 1 }\ntwo() (value: Int) { value = 2 }\n";
|
|
for operation in [
|
|
"timeout(run(one()), 1, two)",
|
|
"race(run(one()), run(two()))",
|
|
] {
|
|
assert_eq!(
|
|
linked(&format!(
|
|
"{prefix}main() (value: Int <= 1) {{ value = {operation} }}"
|
|
))
|
|
.unwrap_err()
|
|
.code,
|
|
"C011"
|
|
);
|
|
assert!(
|
|
linked(&format!(
|
|
"{prefix}main() (value: Int <= 2) {{ value = {operation} }}"
|
|
))
|
|
.is_ok()
|
|
);
|
|
}
|
|
}
|