feat(graph): warn when the visit cap is disabled
validate_timeouts now also flags settings.max_loop_iterations: 0, ahead of the settings.timeout: 0 warning so both opt-outs read top-to-bottom as they appear in settings. (design §3.14 / C22)
This commit is contained in:
1 file changed
+45
-2
+45
-2
@@ -585,9 +585,17 @@ impl GraphValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `timeout: 0` is the author's explicit opt-out of the wall-clock
|
/// Explicit `0` opt-outs on `settings` and node bounds: a `timeout: 0`
|
||||||
/// bound. It is legal; the warning only makes the choice visible.
|
/// disables the wall-clock bound and `max_loop_iterations: 0` disables the
|
||||||
|
/// per-node visit cap. Both are legal; the warnings only make the choice
|
||||||
|
/// visible.
|
||||||
fn validate_timeouts(&self, graph: &Graph, result: &mut ValidationResult) {
|
fn validate_timeouts(&self, graph: &Graph, result: &mut ValidationResult) {
|
||||||
|
if graph.settings.max_loop_iterations == 0 {
|
||||||
|
result.warning(ValidationError::new(
|
||||||
|
"settings.max_loop_iterations: 0 disables the per-node visit cap; a \
|
||||||
|
non-converging loop runs until an enclosing timeout or abort",
|
||||||
|
));
|
||||||
|
}
|
||||||
if graph.settings.timeout == Some(0) {
|
if graph.settings.timeout == Some(0) {
|
||||||
result.warning(ValidationError::new(
|
result.warning(ValidationError::new(
|
||||||
"settings.timeout: 0 disables the graph wall-clock bound; the run \
|
"settings.timeout: 0 disables the graph wall-clock bound; the run \
|
||||||
@@ -3328,6 +3336,41 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn max_loop_iterations_zero_warns() {
|
||||||
|
let mut graph = graph_with(vec![("e", end_node("e"))], "e");
|
||||||
|
graph.settings.max_loop_iterations = 0;
|
||||||
|
|
||||||
|
let result = validator().validate(&graph);
|
||||||
|
|
||||||
|
assert!(result.is_valid());
|
||||||
|
let w = timeout_warnings(&result);
|
||||||
|
assert_eq!(w.len(), 1, "{:?}", result.warnings);
|
||||||
|
assert!(w[0].node_id.is_none());
|
||||||
|
assert_eq!(
|
||||||
|
w[0].message,
|
||||||
|
"settings.max_loop_iterations: 0 disables the per-node visit cap; a non-converging \
|
||||||
|
loop runs until an enclosing timeout or abort"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn max_loop_iterations_nonzero_does_not_warn() {
|
||||||
|
let mut graph = graph_with(vec![("e", end_node("e"))], "e");
|
||||||
|
graph.settings.max_loop_iterations = 5;
|
||||||
|
|
||||||
|
let result = validator().validate(&graph);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
!result
|
||||||
|
.warnings
|
||||||
|
.iter()
|
||||||
|
.any(|w| w.message.contains("max_loop_iterations: 0")),
|
||||||
|
"non-zero cap should not warn: {:?}",
|
||||||
|
result.warnings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn map_max_concurrency_zero_errors() {
|
fn map_max_concurrency_zero_errors() {
|
||||||
let mut map = map_node_basic("m", "br", Some("end"));
|
let mut map = map_node_basic("m", "br", Some("end"));
|
||||||
|
|||||||
Reference in new issue
Block a user