117 lines
4.5 KiB
Rust
117 lines
4.5 KiB
Rust
use super::checked;
|
|
|
|
#[test]
|
|
fn unconstrained_parameters_do_not_expand_clause_products() {
|
|
let inputs = (0..40)
|
|
.map(|position| format!("flag{position}: Bool"))
|
|
.collect::<Vec<_>>()
|
|
.join(", ");
|
|
let body = (0..40)
|
|
.map(|position| format!("flag{position}"))
|
|
.collect::<Vec<_>>()
|
|
.join(" or ");
|
|
let ordinary = format!("choose({inputs}) (answer: Bool) {{ answer = {body} }}\n");
|
|
assert!(checked(&ordinary).is_ok());
|
|
let clause = |pattern: &str| {
|
|
format!("choose(test: {pattern}, {inputs}) (answer: Bool) {{ answer = {body} }}\n")
|
|
};
|
|
assert!(checked(&(clause("true") + &clause("false"))).is_ok());
|
|
assert_eq!(checked(&clause("true")).unwrap_err().code, "C009");
|
|
assert_eq!(
|
|
checked(&(clause("Bool") + &clause("false")))
|
|
.unwrap_err()
|
|
.code,
|
|
"C009"
|
|
);
|
|
assert!(checked("type State { One\n Two }\nvalue(input: State, optional: Bool?) (answer: Bool) { answer = optional == null }").is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn choice_coverage_and_payload_contracts() {
|
|
let prefix = "type State { Idle\n Working(value: Int) }\n";
|
|
let valid = "read(value: State.Idle) (answer: Int) { answer = 0 }\nread(value: State.Working(number)) (answer: Int) { answer = number }";
|
|
assert!(checked(&(prefix.to_owned() + valid)).is_ok());
|
|
for (body, code) in [
|
|
(
|
|
"read(value: State.Idle) (answer: Int) { answer = 0 }",
|
|
"C009",
|
|
),
|
|
(
|
|
"read(value: State) (answer: Int) { answer = 0 }\nread(value: State.Idle) (answer: Int) { answer = 1 }",
|
|
"C009",
|
|
),
|
|
(
|
|
"read(value: State.Working) (answer: Int) { answer = 0 }",
|
|
"C005",
|
|
),
|
|
(
|
|
"read(value: State.Working(first, second)) (answer: Int) { answer = first }",
|
|
"C005",
|
|
),
|
|
(
|
|
"read(value: State.Working(value)) (answer: Int) { answer = 0 }",
|
|
"C009",
|
|
),
|
|
(
|
|
"main() (answer: State) { answer = State.Working() }",
|
|
"C005",
|
|
),
|
|
(
|
|
"main() (answer: State) { answer = State.Working(true) }",
|
|
"C005",
|
|
),
|
|
(
|
|
"read(value: State) (answer: Int) { answer = value.value }",
|
|
"C005",
|
|
),
|
|
] {
|
|
let error = checked(&(prefix.to_owned() + body)).unwrap_err();
|
|
assert_eq!(error.code, code, "{body}: {error:?}");
|
|
}
|
|
let wildcard = "read(value: State.Working(_)) (answer: Int) { answer = 1 }\nread(value: other) (answer: Int) { answer = 0 }";
|
|
assert!(checked(&(prefix.to_owned() + wildcard)).is_ok());
|
|
assert_eq!(
|
|
checked("type Cycle { Next(value: Cycle) }")
|
|
.unwrap_err()
|
|
.code,
|
|
"C007"
|
|
);
|
|
assert_eq!(
|
|
checked("type State { Item(value: Row) }\ntype Row { state: State }")
|
|
.unwrap_err()
|
|
.code,
|
|
"C007"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn nullable_domains_and_complements_are_order_independent() {
|
|
for clauses in [
|
|
"read(value: Text) (answer: Int) { answer = length(value) }\nread(value: null) (answer: Int) { answer = -1 }",
|
|
"read(value: null) (answer: Int) { answer = -1 }\nread(value: Text) (answer: Int) { answer = length(value) }",
|
|
"read(value: other) (answer: Int) { answer = length(value) }\nread(value: null) (answer: Int) { answer = -1 }\nread(value: \"x\") (answer: Int) { answer = 1 }",
|
|
] {
|
|
assert!(checked(clauses).is_ok(), "{clauses}");
|
|
}
|
|
for clauses in [
|
|
"read(value: Text?) (answer: Int) { answer = 0 }\nread(value: null) (answer: Int) { answer = 1 }",
|
|
"read(value: \"x\") (answer: Int) { answer = 0 }\nread(value: null) (answer: Int) { answer = 1 }",
|
|
] {
|
|
assert_eq!(checked(clauses).unwrap_err().code, "C009");
|
|
}
|
|
assert!(checked("equal(value: Int?) (answer: Bool) { answer = value == null or null == value or value == 1 or 1 == value }").is_ok());
|
|
assert!(checked("number() (answer: Decimal?) { answer = 1 }").is_ok());
|
|
assert!(checked("number() (answer: Float?) { answer = 1.5 + 2.5 }").is_ok());
|
|
assert!(checked("values() (answer: List<Int>?) { answer = [] }").is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn payload_bindings_do_not_shadow_inputs_or_outputs() {
|
|
for binding in ["value", "answer"] {
|
|
let text = format!(
|
|
"type State {{ Item(number: Int) }}\nread(value: State.Item({binding})) (answer: Int) {{ answer = 1 }}"
|
|
);
|
|
assert_eq!(checked(&text).unwrap_err().code, "C002");
|
|
}
|
|
}
|