Files
core/test/rust/compiler/numeric/handler_range.rs
T
2026-11-03 03:32:07 +00:00

62 lines
3.6 KiB
Rust

use super::super::checked;
#[test]
fn handler_ranges_check_unused_templates_inference_and_forwarding() {
let apply = "apply(route: handler(value: Int >= 1) (answer: Int >= 2)) (answer: Int >= 2) { answer = route(1) }\n";
checked(apply).unwrap();
checked(&(apply.to_owned() + "twice(value: Int) (answer: Int) { answer = 2 }\nmake() (answer: Int >= 2) { answer = apply(twice) }")).unwrap();
assert_eq!(checked(&(apply.to_owned() + "identity(value: Int) (answer: Int) { answer = value }\nmake() (answer: Int) { answer = apply(identity) }")).unwrap_err().code, "C011");
assert_eq!(
checked(
"bad(route: handler(value: Int >= 1) (answer: Int)) (answer: Int) { answer = route(0) }"
)
.unwrap_err()
.code,
"C011"
);
checked(&(apply.to_owned() + "forward(route: handler(value: Int) (answer: Int >= 3)) (answer: Int >= 2) { answer = apply(route) }")).unwrap();
for contract in [
"handler(value: Int >= 2) (answer: Int >= 3)",
"handler(value: Int) (answer: Int >= 1)",
] {
assert_eq!(
checked(&format!(
"{apply}forward(route: {contract}) (answer: Int) {{ answer = apply(route) }}"
))
.unwrap_err()
.code,
"C011"
);
}
}
#[test]
fn prototype_cache_keeps_distinct_range_contracts() {
let prefix = "first(route: handler(value: Int) (answer: Int >= 2)) (answer: Int >= 2) { answer = route(1) }\n";
assert_eq!(checked(&(prefix.to_owned() + "second(route: handler(value: Int) (answer: Int >= 1)) (answer: Int >= 2) { answer = route(1) }")).unwrap_err().code, "C011");
assert_eq!(checked("first(route: handler(value: Int >= 1) (answer: Int)) (answer: Int) { answer = route(1) }\nsecond(route: handler(value: Int >= 2) (answer: Int)) (answer: Int) { answer = route(1) }").unwrap_err().code, "C011");
}
#[test]
fn collection_handlers_check_items_context_and_repeated_state() {
checked("valid(route: handler(value: Int >= 1) (answer: Int >= 2)) (answer: List<Int>) { answer = each(route, [1, 2]) }").unwrap();
for body in [
"bad(route: handler(value: Int >= 1) (answer: Int), values: List<Int>) (answer: List<Int>) { answer = each(route, values) }",
"bad(route: handler(value: Int >= 1) (answer: Int)) (answer: List<Int>) { answer = each(route, [0, 1]) }",
"bad(route: handler(value: Int, state: Int >= 1) (answer: Int)) (answer: Int) { answer = reduce(route, [1, 2], 1) }",
"bad(route: handler(value: Int, context: Int >= 1) (answer: Int)) (answer: List<Int>) { answer = each(route, [1], 0) }",
] {
assert_eq!(checked(body).unwrap_err().code, "C011", "{body}");
}
checked("valid(route: handler(value: Int, state: Int >= 1) (answer: Int >= 1)) (answer: Int >= 1) { answer = reduce(route, [1, 2], 1) }").unwrap();
checked("valid(route: handler(value: Int >= 0 and <= 255) (answer: Int), values: Bytes) (answer: List<Int>) { answer = each(route, values) }").unwrap();
}
#[test]
fn failing_collection_inputs_do_not_produce_invalid_values() {
let prefix =
"type Problem { error Failed }\nabortOperation() (answer: Int) { fail(Problem.Failed) }\n";
checked(&(prefix.to_owned() + "apply(route: handler(value: Int, context: Int >= 1) (answer: Int)) (answer: List<Int>) { answer = each(route, [1], abortOperation()) }")).unwrap();
checked("type Problem { error Failed }\nabortOperation(value: Int, state: Int) (answer: Int) { fail(Problem.Failed) }\napply(route: handler(value: Int, state: Int >= 1) (answer: Int >= 1)) (answer: Int >= 1) { answer = reduce(route, [1], 1) }\nentry() (answer: Int >= 1) { answer = apply(abortOperation) }").unwrap();
}