cuenv_task_graph/
validation.rs1use crate::{Error, TaskGraph, TaskNodeData};
6
7#[derive(Debug, Clone)]
9pub struct ValidationResult {
10 pub is_valid: bool,
12 pub errors: Vec<Error>,
14}
15
16impl ValidationResult {
17 #[must_use]
19 pub fn valid() -> Self {
20 Self {
21 is_valid: true,
22 errors: vec![],
23 }
24 }
25
26 #[must_use]
28 pub fn invalid(errors: Vec<Error>) -> Self {
29 Self {
30 is_valid: false,
31 errors,
32 }
33 }
34}
35
36impl<T: TaskNodeData> TaskGraph<T> {
37 #[must_use]
45 pub fn validate(&self) -> ValidationResult {
46 let mut errors = Vec::new();
47
48 if self.has_cycles() {
49 errors.push(Error::CycleDetected {
50 message: "Task dependency graph contains cycles".to_string(),
51 });
52 }
53
54 if errors.is_empty() {
55 ValidationResult::valid()
56 } else {
57 ValidationResult::invalid(errors)
58 }
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[derive(Clone, Debug, Default)]
67 struct TestTask {
68 depends_on: Vec<String>,
69 }
70
71 impl TaskNodeData for TestTask {
72 fn dependency_names(&self) -> impl Iterator<Item = &str> {
73 self.depends_on.iter().map(String::as_str)
74 }
75 }
76
77 #[test]
78 fn test_validate_empty_graph() {
79 let graph: TaskGraph<TestTask> = TaskGraph::new();
80 let result = graph.validate();
81 assert!(result.is_valid);
82 assert!(result.errors.is_empty());
83 }
84
85 #[test]
86 fn test_validate_valid_graph() {
87 let mut graph = TaskGraph::new();
88 graph
89 .add_task("a", TestTask { depends_on: vec![] })
90 .unwrap();
91 graph
92 .add_task(
93 "b",
94 TestTask {
95 depends_on: vec!["a".to_string()],
96 },
97 )
98 .unwrap();
99 graph.add_dependency_edges().unwrap();
100
101 let result = graph.validate();
102 assert!(result.is_valid);
103 }
104
105 #[test]
106 fn test_validate_cyclic_graph() {
107 let mut graph = TaskGraph::new();
108 graph
109 .add_task(
110 "a",
111 TestTask {
112 depends_on: vec!["b".to_string()],
113 },
114 )
115 .unwrap();
116 graph
117 .add_task(
118 "b",
119 TestTask {
120 depends_on: vec!["a".to_string()],
121 },
122 )
123 .unwrap();
124 graph.add_dependency_edges().unwrap();
125
126 let result = graph.validate();
127 assert!(!result.is_valid);
128 assert_eq!(result.errors.len(), 1);
129 }
130}