87 lines
3.1 KiB
Rust
87 lines
3.1 KiB
Rust
use super::linked;
|
|
|
|
#[test]
|
|
fn parallel_consumers_select_threads_or_runtime_from_their_body() {
|
|
let prefix = "work(value: Int) () pure {}\n";
|
|
let program = linked(&format!(
|
|
"{prefix}main() () {{ parallelEach(work, [1, 2], 2) }}"
|
|
))
|
|
.unwrap();
|
|
let main = program
|
|
.functions
|
|
.iter()
|
|
.find(|function| function.signature.name == "main")
|
|
.unwrap();
|
|
assert!(!main.signature.effects.suspend);
|
|
assert!(main.signature.effects.blocking);
|
|
for body in [
|
|
"dever.task.sleep(0)\n parallelEach(work, [1, 2], 2)",
|
|
"parallelEach(work, stream([1, 2]), 2)",
|
|
] {
|
|
let program = linked(&format!("{prefix}main() () {{ {body} }}")).unwrap();
|
|
let main = program
|
|
.functions
|
|
.iter()
|
|
.find(|function| function.signature.name == "main")
|
|
.unwrap();
|
|
assert!(main.signature.effects.suspend);
|
|
assert!(main.signature.effects.schedule);
|
|
assert!(!main.signature.effects.blocking);
|
|
}
|
|
assert!(linked("work(value: Int) () { dever.task.sleep(value) }\nmain() () { parallelEach(work, [0, 1], 2) }").is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn parallel_handlers_keep_typed_outputs_context_and_transfer_boundaries() {
|
|
for (source, code) in [
|
|
(
|
|
"work(value: Int) (answer: Int) { answer = value }\nmain() () { parallelEach(work, [1], 2) }",
|
|
"C005",
|
|
),
|
|
(
|
|
"work(value: Int) () {}\nmain() () { parallelEach(work, [1], true) }",
|
|
"C005",
|
|
),
|
|
(
|
|
"work(value: Int, context: Bool) () {}\nmain() () { parallelEach(work, [1], 2, 3) }",
|
|
"C005",
|
|
),
|
|
(
|
|
"work(value: Stream<Int>) () { close(value) }\nmain(values: List<Stream<Int>>) () { parallelEach(work, values, 2) }",
|
|
"C013",
|
|
),
|
|
(
|
|
"work(value: Int) () pure {}\nmain() () pure { parallelEach(work, [1], 2) }",
|
|
"C013",
|
|
),
|
|
(
|
|
"work(value: Int) () {}\nmain(values: Stream<Int>) () { dever.task.sleep(0)\n parallelEach(work, values, 2) }",
|
|
"C013",
|
|
),
|
|
(
|
|
"leaf(value: Int) () {}\nwork(value: Int) () { parallelEach(leaf, [value], 2) }\nmain() () { dever.task.sleep(0)\n parallelEach(work, [1], 2) }",
|
|
"C013",
|
|
),
|
|
] {
|
|
assert_eq!(linked(source).unwrap_err().code, code, "{source}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn parallel_each_transfers_errors_only_through_valid_handlers() {
|
|
let prefix = "type Result { Done\n error Failed(message: Text) }\nhandle(value: Result) () recover(\"handles each error\") {}\n";
|
|
assert!(
|
|
linked(&format!(
|
|
"{prefix}main() () {{ parallelEach(handle, [Result.Failed(\"reason\")], 2) }}"
|
|
))
|
|
.is_ok()
|
|
);
|
|
assert!(
|
|
linked(&format!(
|
|
"{prefix}main() () {{ parallelEach(handle, stream([Result.Failed(\"reason\")]), 2) }}"
|
|
))
|
|
.is_ok()
|
|
);
|
|
assert_eq!(linked("type Result { error Failed(values: List<Stream<Int>>) }\nwork(value: Int) () { fail(Result.Failed([])) }\nmain() () { parallelEach(work, [1], 2) }").unwrap_err().code, "C013");
|
|
}
|