rez_next_solver/astar/
test_framework.rs1use super::search_state::{ConflictType, DependencyConflict, SearchState};
4use rez_next_package::{Package, PackageRequirement};
5
6pub fn test_search_state_basic() -> Result<(), String> {
8 let state = SearchState::new_initial(vec![]);
9 if state.depth != 0 {
10 return Err("Initial state should have depth 0".to_string());
11 }
12 if !state.resolved_packages.is_empty() {
13 return Err("Initial state should have no resolved packages".to_string());
14 }
15 if !state.conflicts.is_empty() {
16 return Err("Initial state should have no conflicts".to_string());
17 }
18 if !state.is_goal() {
19 return Err("Empty state should be a goal".to_string());
20 }
21 Ok(())
22}
23
24pub fn test_search_state_with_requirements() -> Result<(), String> {
26 let req = PackageRequirement::new("python".to_string());
27 let state = SearchState::new_initial(vec![req]);
28
29 if state.is_goal() {
30 return Err("State with pending requirements should not be a goal".to_string());
31 }
32 if state.pending_requirements.len() != 1 {
33 return Err("State should have exactly 1 pending requirement".to_string());
34 }
35 Ok(())
36}
37
38pub fn test_state_transition() -> Result<(), String> {
40 let req = PackageRequirement::new("python".to_string());
41 let parent = SearchState::new_initial(vec![req.clone()]);
42
43 let pkg = Package::new("python".to_string());
44 let mut child = SearchState::new_from_parent(&parent, pkg, vec![], 1.0);
45 child.remove_requirement(&req);
46
47 if !child.resolved_packages.contains_key("python") {
48 return Err("Python should be resolved in child state".to_string());
49 }
50 if child.depth != 1 {
51 return Err(format!("Child depth should be 1, got {}", child.depth));
52 }
53
54 Ok(())
55}
56
57pub fn test_conflict_detection() -> Result<(), String> {
59 let mut state = SearchState::new_initial(vec![]);
60 state.add_conflict(DependencyConflict::new(
61 "conflicting_pkg".to_string(),
62 vec!["req_a".to_string(), "req_b".to_string()],
63 1.0,
64 ConflictType::VersionConflict,
65 ));
66
67 if state.conflicts.is_empty() {
68 return Err("State should have a version conflict".to_string());
69 }
70 if !state.is_valid() {
72 return Err("State with only VersionConflict should still be valid".to_string());
73 }
74
75 let mut state2 = SearchState::new_initial(vec![]);
76 state2.add_conflict(DependencyConflict::new(
77 "missing_pkg".to_string(),
78 vec![],
79 1.0,
80 ConflictType::MissingPackage,
81 ));
82 if state2.is_valid() {
83 return Err("State with MissingPackage conflict should be invalid".to_string());
84 }
85
86 Ok(())
87}
88
89pub fn run_framework_tests() -> Result<(), String> {
91 test_search_state_basic()?;
92 test_search_state_with_requirements()?;
93 test_state_transition()?;
94 test_conflict_detection()?;
95 Ok(())
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use crate::astar::StatePool;
102
103 #[test]
104 fn test_run_framework_tests() {
105 run_framework_tests().expect("All framework tests should pass");
106 }
107
108 #[test]
109 fn test_state_pool_basic() {
110 let mut pool = StatePool::new(5);
111 assert_eq!(pool.size(), 0);
112 let s = pool.get_state();
113 pool.return_state(s);
114 assert_eq!(pool.size(), 1);
115 }
116}