Handle adding vector of statuses.

This commit is contained in:
James Pace 2026-06-20 11:41:08 -04:00
parent 4cf54d18c3
commit 6e714a2325
2 changed files with 129 additions and 14 deletions

View File

@ -38,9 +38,11 @@ impl DiagnosticStatus {
hardware_id: String, hardware_id: String,
values: BTreeMap<String, String>, values: BTreeMap<String, String>,
) -> Self { ) -> Self {
let cleaned_name = Self::clean_name(&name);
Self { Self {
level: level, level: level,
name: name, name: cleaned_name,
message: message, message: message,
hardware_id: hardware_id, hardware_id: hardware_id,
values: values, values: values,
@ -132,6 +134,15 @@ impl DiagnosticStatus {
to_return.name = self.get_child_name(); to_return.name = self.get_child_name();
return to_return; return to_return;
} }
fn clean_name(name: &str) -> String {
// Remove prefix "/"
let without_prefix = name.strip_prefix("/").unwrap_or(name);
// and suffix
let without_suffix = name.strip_suffix("/").unwrap_or(without_prefix);
return without_suffix.to_owned();
}
} }
#[cfg(test)] #[cfg(test)]
@ -180,4 +191,24 @@ mod tests {
assert!(parent_names[1] == "b"); assert!(parent_names[1] == "b");
assert!(child_name == "c"); assert!(child_name == "c");
} }
#[test]
fn diagnostic_name_cleaning() {
let level = DiagnosticLevel::OK;
let name = "/a";
let message = "I'm ok";
let hardware_id = "";
let values = BTreeMap::<String, String>::new();
let diag_status = DiagnosticStatus::new(
level,
name.to_owned(),
message.to_owned(),
hardware_id.to_owned(),
values,
);
assert!(diag_status.name_is_basic());
assert!(diag_status.name() == "a");
}
} }

View File

@ -89,6 +89,22 @@ impl DiagnosticGraph {
Ok(result) Ok(result)
} }
pub fn child_of_with_name(
&self,
parent: &limbo_graph::Key,
desired_child_name: &str,
) -> anyhow::Result<Option<limbo_graph::Key>> {
let all_children = self.children_of(parent)?;
for child in all_children.iter() {
let child_name = self.value_of(&child)?.name();
if child_name == desired_child_name {
return Ok(Some(child.clone()));
}
}
return Ok(None);
}
pub fn add_status(&mut self, status: DiagnosticStatus) -> anyhow::Result<()> { pub fn add_status(&mut self, status: DiagnosticStatus) -> anyhow::Result<()> {
// If I'm basic I just need to be added as a child of the root. // If I'm basic I just need to be added as a child of the root.
if status.name_is_basic() { if status.name_is_basic() {
@ -105,6 +121,8 @@ impl DiagnosticGraph {
'parent_loop: for parent_name in parent_names.iter() { 'parent_loop: for parent_name in parent_names.iter() {
let children = self.graph.children_of(&cur_key)?; let children = self.graph.children_of(&cur_key)?;
// There are no children of this parent, so we can add
// the parent and go to the next parent.
if children.len() == 0 { if children.len() == 0 {
let holder_for_parent = DiagnosticStatus::from_name(parent_name.clone()); let holder_for_parent = DiagnosticStatus::from_name(parent_name.clone());
cur_key = self cur_key = self
@ -112,11 +130,13 @@ impl DiagnosticGraph {
.add(DiagnosticNode::DiagnosticStatus(holder_for_parent), cur_key)?; .add(DiagnosticNode::DiagnosticStatus(holder_for_parent), cur_key)?;
continue 'parent_loop; continue 'parent_loop;
} }
'child_loop: for child in children { // This parent does have children, look at them and
// update loop if appropriate.
for child in children {
let child_node = self.graph.value_of(&child)?; let child_node = self.graph.value_of(&child)?;
if child_node.is_root() { if child_node.is_root() {
// child node can't be root, but we'll catch here anyway. // A child node can't be root.
continue 'child_loop; return Err(anyhow!("A child node can't be root!"));
} }
if child_node.value().unwrap().name() == *parent_name { if child_node.value().unwrap().name() == *parent_name {
// The child node matched the parent we were looking for. // The child node matched the parent we were looking for.
@ -133,11 +153,34 @@ impl DiagnosticGraph {
.add(DiagnosticNode::DiagnosticStatus(holder_for_parent), cur_key)?; .add(DiagnosticNode::DiagnosticStatus(holder_for_parent), cur_key)?;
} }
// We've updated all the parents, so we can add ourselves now. // We've updated all the parents, so we can add ourselves now.
self.graph.add(
DiagnosticNode::DiagnosticStatus(status.copy_with_child_name()),
cur_key,
)?;
// Do we already exist as a child of parent?
let children_of_this_parent = self.graph.children_of(&cur_key)?;
let mut names_of_children_of_this_parent = children_of_this_parent.iter().map(|x| {
self.graph
.value_of(&x)
.expect("Given child not in graph.")
.value()
.expect("Given root node as child?")
.name()
});
let child_in_children_of_this_parent =
names_of_children_of_this_parent.any(|x| x == status.get_child_name());
if !child_in_children_of_this_parent {
// If we don't we can be added.
self.graph.add(
DiagnosticNode::DiagnosticStatus(status.copy_with_child_name()),
cur_key,
)?;
}
Ok(())
}
pub fn add_status_vec(&mut self, statuses: &Vec<DiagnosticStatus>) -> anyhow::Result<()> {
for status in statuses {
self.add_status(status.clone())?;
}
Ok(()) Ok(())
} }
} }
@ -145,25 +188,27 @@ impl DiagnosticGraph {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use alloc::vec;
#[test] fn make_a_status_with_name(name: &str) -> DiagnosticStatus {
fn add_one_to_graph() -> anyhow::Result<()> {
let level = DiagnosticLevel::OK; let level = DiagnosticLevel::OK;
let name = "/a/b/c";
let message = "I'm ok"; let message = "I'm ok";
let hardware_id = ""; let hardware_id = "";
let values = BTreeMap::<String, String>::new(); let values = BTreeMap::<String, String>::new();
let diag_status = DiagnosticStatus::new( DiagnosticStatus::new(
level, level,
name.to_owned(), name.to_owned(),
message.to_owned(), message.to_owned(),
hardware_id.to_owned(), hardware_id.to_owned(),
values, values,
); )
}
#[test]
fn add_one_to_graph() -> anyhow::Result<()> {
let mut graph = DiagnosticGraph::new(); let mut graph = DiagnosticGraph::new();
graph.add_status(diag_status)?; graph.add_status(make_a_status_with_name("/a/b/c"))?;
let first_child_keys = graph.children_of(&graph.root())?; let first_child_keys = graph.children_of(&graph.root())?;
assert!(first_child_keys.len() == 1); assert!(first_child_keys.len() == 1);
@ -186,4 +231,43 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
fn add_multiple_to_graph() -> anyhow::Result<()> {
let statuses = vec![
make_a_status_with_name("/a"),
make_a_status_with_name("/a/b"),
make_a_status_with_name("/a/b/c"),
make_a_status_with_name("/a/d/e"),
make_a_status_with_name("/a/d/f"),
make_a_status_with_name("/a/d"),
];
let mut graph = DiagnosticGraph::new();
graph.add_status_vec(&statuses)?;
let root_children = graph.children_of(&graph.root())?;
assert!(root_children.len() == 1);
assert!(graph.value_of(&root_children[0])?.name() == "a");
let children_of_a = graph.children_of(&root_children[0])?;
let mut children_of_a_names = children_of_a
.iter()
.map(|x| graph.value_of(&x).expect("Value of failed.").name());
assert!(children_of_a.len() == 2);
assert!(children_of_a_names.any(|x| x == "b"));
assert!(children_of_a_names.any(|x| x == "d"));
let b_key = graph.child_of_with_name(&root_children[0], "b")?;
assert!(b_key.is_some());
let b_children = graph.children_of(&b_key.unwrap())?;
assert!(b_children.len() == 1);
let d_key = graph.child_of_with_name(&root_children[0], "d")?;
assert!(d_key.is_some());
let d_children = graph.children_of(&d_key.unwrap())?;
assert!(d_children.len() == 2);
Ok(())
}
} }