85 lines
3.1 KiB
Rust
85 lines
3.1 KiB
Rust
use super::linked;
|
|
use dever::compiler::build;
|
|
|
|
#[test]
|
|
fn channel_types_require_transferable_elements_and_typed_values() {
|
|
assert!(linked("main() () { values = channel(List<Int?>, 2)\n send(values, [null, 1])\n close(values) }").is_ok());
|
|
assert!(linked("main() () { values = channel(Channel<Int>, 1)\n send(values, channel(Int, 1))\n close(values) }").is_ok());
|
|
assert!(linked("type Message { Value(value: Int?) }\nmain() () { values = channel(Message, 1)\n send(values, Message.Value(null))\n close(values) }").is_ok());
|
|
for (source, code) in [
|
|
("main() () { values = channel(Int, true) }", "C005"),
|
|
("main() () { values = channel(Int?, 1) }", "C013"),
|
|
("main(values: Channel<Int?>) () { close(values) }", "C013"),
|
|
(
|
|
"type Unused { values: Channel<Int?> }\nmain() () {}",
|
|
"C013",
|
|
),
|
|
(
|
|
"main() () { values = channel(Int, 1)\n send(values, true) }",
|
|
"C005",
|
|
),
|
|
("main() () { values = channel(Stream<Int>, 1) }", "C013"),
|
|
(
|
|
"main() () { values = channel(List<Stream<Int>>, 1) }",
|
|
"C013",
|
|
),
|
|
(
|
|
"main() () { values = channel(Map<Channel<Int>, Int>, 1) }",
|
|
"C005",
|
|
),
|
|
("type Loop { next: Channel<Loop> }\nmain() () {}", "C007"),
|
|
("main() () pure { values = channel(Int, 1) }", "C013"),
|
|
(
|
|
"main(values: Stream<Int>, channel: Channel<Int>) () { close(channel)\n close(values) }",
|
|
"C013",
|
|
),
|
|
] {
|
|
assert_eq!(linked(source).unwrap_err().code, code, "{source}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn send_transfers_errors_and_receive_requires_handling_them() {
|
|
let prefix = "type Result { Done\n error Failed(message: Text) }\n";
|
|
assert!(linked(&format!("{prefix}main() () {{ values = channel(Result, 1)\n send(values, Result.Failed(\"reason\"))\n close(values) }}")).is_ok());
|
|
assert_eq!(
|
|
linked(&format!(
|
|
"{prefix}main(values: Channel<Result>) () {{ lost = receive(values)\n close(values) }}"
|
|
))
|
|
.unwrap_err()
|
|
.code,
|
|
"C012"
|
|
);
|
|
assert!(
|
|
linked(&format!(
|
|
"{prefix}main(values: Channel<Result>) (answer: Result?) {{ answer = receive(values) }}"
|
|
))
|
|
.is_ok()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn channel_creation_and_type_references_enable_dependency_without_suspending() {
|
|
for (source, required) in [
|
|
(
|
|
"main() (value: Channel<Int>) { value = channel(Int, 1) }",
|
|
true,
|
|
),
|
|
("main() (value: Channel<Int>?) { value = null }", true),
|
|
("type Unused { value: Channel<Int> }\nmain() () {}", false),
|
|
] {
|
|
let program = linked(source).unwrap();
|
|
let main = program
|
|
.functions
|
|
.iter()
|
|
.position(|function| function.signature.name == "main")
|
|
.unwrap();
|
|
assert!(!program.functions[main].signature.effects.suspend);
|
|
assert!(!program.functions[main].signature.effects.schedule);
|
|
assert_eq!(
|
|
build::runtime_features(&program, &program.reachable([main])).contains(&"task"),
|
|
required
|
|
);
|
|
}
|
|
}
|