use std::{borrow::Borrow, cmp::Ordering, collections::HashMap};
use crate::xray_exporter::{
error::ConstraintError,
types::{DocumentBuilderHeader, Id, TraceId},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct NodeId(usize);
struct TreeNode<T> {
level: usize,
parent: Option<NodeId>,
first_child: Option<NodeId>,
last_child: Option<NodeId>,
previous_sibling: Option<NodeId>,
next_sibling: Option<NodeId>,
previous_cousin: Option<NodeId>,
next_cousin: Option<NodeId>,
data: T,
}
impl<T> core::fmt::Debug for TreeNode<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TreeNode")
.field("level", &self.level)
.field("parent", &self.parent)
.field("first_child", &self.first_child)
.field("last_child", &self.last_child)
.field("previous_sibling", &self.previous_sibling)
.field("next_sibling", &self.next_sibling)
.field("previous_cousin", &self.previous_cousin)
.field("next_cousin", &self.next_cousin)
.finish()
}
}
impl<T> TreeNode<T> {
fn new(level: usize, data: T) -> Self {
Self {
level,
parent: None,
first_child: None,
last_child: None,
previous_sibling: None,
next_sibling: None,
previous_cousin: None,
next_cousin: None,
data,
}
}
}
#[derive(Debug, Clone, Copy)]
struct TreeLevel {
first: NodeId,
last: NodeId,
}
#[derive(Debug)]
struct Tree<T> {
nodes: Vec<TreeNode<T>>,
levels: Vec<TreeLevel>,
}
impl<T> Tree<T> {
fn get(&self, node_id: NodeId) -> &TreeNode<T> {
&self.nodes[node_id.0]
}
fn _get_mut(&mut self, node_id: NodeId) -> &mut TreeNode<T> {
&mut self.nodes[node_id.0]
}
fn _get_mut_nodes(
&mut self,
node1_id: NodeId,
node2_id: NodeId,
) -> (&mut TreeNode<T>, &mut TreeNode<T>) {
match node1_id.0.cmp(&node2_id.0) {
Ordering::Less => {
let (s1, s2) = self.nodes.split_at_mut(node2_id.0);
(&mut s1[node1_id.0], &mut s2[0])
}
Ordering::Greater => {
let (s1, s2) = self.nodes.split_at_mut(node1_id.0);
(&mut s2[0], &mut s1[node2_id.0])
}
Ordering::Equal => panic!("Cannot create 2 mut ref for the same node"),
}
}
fn _insert_node_before(&mut self, node_id: NodeId, existing_node_id: NodeId) {
let (node, existing_node) = self._get_mut_nodes(node_id, existing_node_id);
node.parent = existing_node.parent;
node.previous_sibling = existing_node.previous_sibling;
node.next_sibling = Some(existing_node_id);
existing_node.previous_sibling = Some(node_id);
node.previous_cousin = existing_node.previous_cousin;
existing_node.previous_cousin = None;
let level = node.level;
let previous_sibling = node.previous_sibling;
let previous_cousin = node.previous_cousin;
let parent = node.parent.expect("siblings have a parent by definition");
if let Some(previous_sibling) = previous_sibling {
self._get_mut(previous_sibling).next_sibling = Some(node_id);
}
if let Some(previous_cousin) = previous_cousin {
self._get_mut(previous_cousin).next_cousin = Some(node_id);
}
if self.levels[level].first == existing_node_id {
self.levels[level].first = node_id;
}
let parent_node = self._get_mut(parent);
if parent_node.first_child.expect("this parent have children") == existing_node_id {
parent_node.first_child = Some(node_id);
}
}
fn _insert_node_after(&mut self, node_id: NodeId, existing_node_id: NodeId) {
let (node, existing_node) = self._get_mut_nodes(node_id, existing_node_id);
node.parent = existing_node.parent;
node.next_sibling = existing_node.next_sibling;
node.previous_sibling = Some(existing_node_id);
existing_node.next_sibling = Some(node_id);
node.next_cousin = existing_node.next_cousin;
existing_node.next_cousin = None;
let level = node.level;
let next_sibling = node.next_sibling;
let next_cousin = node.next_cousin;
let parent = node.parent.expect("siblings have a parent by definition");
if let Some(next_sibling) = next_sibling {
self._get_mut(next_sibling).previous_sibling = Some(node_id);
}
if let Some(next_cousin) = next_cousin {
self._get_mut(next_cousin).previous_cousin = Some(node_id);
}
if self.levels[level].last == existing_node_id {
self.levels[level].last = node_id;
}
let parent_node = self._get_mut(parent);
if parent_node.last_child.expect("this parent have children") == existing_node_id {
parent_node.last_child = Some(node_id);
}
}
fn _append_siblings_at_lvl(&mut self, first_sibling_id: NodeId, last_sibling_id: NodeId) {
let level = self.get(first_sibling_id).level;
if let Some(lvl) = self.levels.get_mut(level) {
let previous_last = lvl.last;
lvl.last = last_sibling_id;
self._get_mut(previous_last).next_cousin = Some(first_sibling_id);
self._get_mut(first_sibling_id).previous_cousin = Some(previous_last);
} else {
self.levels.push(TreeLevel {
first: first_sibling_id,
last: last_sibling_id,
});
}
}
fn _remove_siblings_from_lvl(&mut self, first_sibling_id: NodeId, last_sibling_id: NodeId) {
let first_sibling = self._get_mut(first_sibling_id);
let previous_sibling = first_sibling.previous_sibling;
let previous_cousin = first_sibling.previous_cousin;
first_sibling.previous_sibling = None;
first_sibling.previous_cousin = None;
let last_sibling = self._get_mut(last_sibling_id);
let next_sibling = last_sibling.next_sibling;
let next_cousin = last_sibling.next_cousin;
last_sibling.next_sibling = None;
last_sibling.next_cousin = None;
let parent_id = last_sibling.parent;
let level = last_sibling.level;
let level = &mut self.levels[level];
match (previous_cousin, next_cousin) {
(Some(previous_cousin), Some(next_cousin)) => {
self._get_mut(previous_cousin).next_cousin = Some(next_cousin);
self._get_mut(next_cousin).previous_cousin = Some(previous_cousin);
}
(Some(previous_cousin), None) => {
if let Some(next_sibling) = next_sibling {
self._get_mut(previous_cousin).next_cousin = Some(next_sibling);
self._get_mut(next_sibling).previous_cousin = Some(previous_cousin);
} else if level.last == last_sibling_id {
level.last = previous_cousin;
self._get_mut(previous_cousin).next_cousin = None;
} else {
unreachable!("would violate tree invariants");
}
}
(None, Some(next_cousin)) => {
if let Some(previous_sibling) = previous_sibling {
self._get_mut(next_cousin).previous_cousin = Some(previous_sibling);
self._get_mut(previous_sibling).next_cousin = Some(next_cousin);
} else if level.first == first_sibling_id {
level.first = next_cousin;
self._get_mut(next_cousin).previous_cousin = None;
} else {
unreachable!("would violate tree invariants");
}
}
(None, None) => {
if level.first == first_sibling_id && level.last == last_sibling_id {
panic!("cannot be used to remove an entire level");
} else if level.first == first_sibling_id {
level.first = next_sibling.expect("would violate tree invariants");
} else if level.last == last_sibling_id {
level.last = previous_sibling.expect("would violate tree invariants");
}
}
}
if let Some(parent_id) = parent_id {
let parent = self._get_mut(parent_id);
let first_child = parent.first_child.expect("this parent have children");
let last_child = parent.last_child.expect("this parent have children");
match (previous_sibling, next_sibling) {
(Some(previous_sibling), Some(next_sibling)) => {
self._get_mut(previous_sibling).next_sibling = Some(next_sibling);
self._get_mut(next_sibling).previous_sibling = Some(previous_sibling);
}
(Some(previous_sibling), None) if last_child == last_sibling_id => {
parent.last_child = Some(previous_sibling);
self._get_mut(previous_sibling).next_sibling = None;
}
(None, Some(next_sibling)) if first_child == first_sibling_id => {
parent.first_child = Some(next_sibling);
self._get_mut(next_sibling).previous_sibling = None;
}
(None, None)
if first_child == first_sibling_id && last_child == last_sibling_id => {}
_ => {
unreachable!("would violate tree invariants");
}
}
}
}
fn _update_siblings_lvl(
&mut self,
first_sibling_id: NodeId,
last_sibling_id: NodeId,
new_level: usize,
) {
let mut cursor = first_sibling_id;
loop {
let node = self._get_mut(cursor);
node.level = new_level;
if cursor == last_sibling_id {
break;
}
if let Some(next) = node.next_sibling {
cursor = next;
} else {
break;
}
}
}
fn _move_node_subtree(&mut self, node_id: NodeId) {
let node = self.get(node_id);
let level = node.level;
let first_child_id = node.first_child;
let last_child_id = node.last_child;
if let (Some(first_child_id), Some(last_child_id)) = (first_child_id, last_child_id) {
self._remove_siblings_from_lvl(first_child_id, last_child_id);
self._update_siblings_lvl(first_child_id, last_child_id, level + 1);
self._append_siblings_at_lvl(first_child_id, last_child_id);
let mut child = first_child_id;
loop {
self._move_node_subtree(child);
if let Some(next) = self.get(child).next_sibling {
child = next;
} else {
break;
}
}
}
}
fn set_node_data(&mut self, node_id: NodeId, data: T) {
self._get_mut(node_id).data = data;
}
}
impl<T: Ord> Tree<T> {
fn _insert_sibling_sorted(&mut self, node_id: NodeId, parent_node_id: NodeId) {
let parent_node = self._get_mut(parent_node_id);
match (parent_node.first_child, parent_node.last_child) {
(Some(first_child), Some(last_child)) => {
let node_data = &self.get(node_id).data;
let mut forward_cursor = first_child;
let mut backward_cursor = last_child;
loop {
let forward_node = self.get(forward_cursor);
if *node_data < forward_node.data {
self._insert_node_before(node_id, forward_cursor);
break;
}
if forward_node.next_sibling.is_none() {
self._insert_node_after(node_id, forward_cursor);
break;
}
forward_cursor = forward_node.next_sibling.unwrap();
let backward_node = self.get(backward_cursor);
if *node_data >= backward_node.data {
self._insert_node_after(node_id, backward_cursor);
break;
}
backward_cursor = backward_node.previous_sibling.expect("Cannot be None because forward_node.next_sibling would also be None so we already break");
}
}
(None, None) => {
parent_node.first_child = Some(node_id);
parent_node.last_child = Some(node_id);
self._get_mut(node_id).parent = Some(parent_node_id);
self._append_siblings_at_lvl(node_id, node_id);
}
_ => unreachable!("first and last child are always both None or both Some"),
}
}
fn insert_sorted(&mut self, data: T, parent_node_id: Option<NodeId>) -> NodeId {
let node_id = NodeId(self.nodes.len());
let node = if let Some(parent_node_id) = parent_node_id {
TreeNode::new(self.get(parent_node_id).level + 1, data)
} else {
TreeNode::new(0, data)
};
self.nodes.push(node);
if let Some(parent_node_id) = parent_node_id {
self._insert_sibling_sorted(node_id, parent_node_id);
} else {
self._append_siblings_at_lvl(node_id, node_id);
};
node_id
}
fn reparent_sorted(&mut self, node_id: NodeId, new_parent_node_id: NodeId) {
let parent_level = self.get(new_parent_node_id).level;
self._remove_siblings_from_lvl(node_id, node_id);
self._update_siblings_lvl(node_id, node_id, parent_level + 1);
self._insert_sibling_sorted(node_id, new_parent_node_id);
self._move_node_subtree(node_id);
}
}
struct Index<K, V> {
inner: HashMap<K, V>,
}
impl<K: Eq + std::hash::Hash, V> Index<K, V> {
fn insert(&mut self, key: K, value: V) {
self.inner.insert(key, value);
}
fn get<Q>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: ?Sized + Eq + std::hash::Hash,
{
self.inner.get(key)
}
}
#[derive(Debug)]
struct DocumentBuilderHeaderWrapper(Option<DocumentBuilderHeader>);
impl Eq for DocumentBuilderHeaderWrapper {}
impl PartialEq for DocumentBuilderHeaderWrapper {
fn eq(&self, other: &Self) -> bool {
self.0.map(|h| h.start_time) == other.0.map(|h| h.start_time)
}
}
impl Ord for DocumentBuilderHeaderWrapper {
fn cmp(&self, other: &Self) -> Ordering {
match (
self.0.and_then(|h| h.start_time),
other.0.and_then(|h| h.start_time),
) {
(Some(h1), Some(h2)) => h1.total_cmp(&h2),
_ => unreachable!("Placeholders never have parent, so no siblings to sort either"),
}
}
}
impl PartialOrd for DocumentBuilderHeaderWrapper {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub(super) struct DocumentBuilderHeaderTree {
header_tree: Tree<DocumentBuilderHeaderWrapper>,
node_index: Index<(TraceId, Id), NodeId>,
}
impl DocumentBuilderHeaderTree {
pub fn new(size: usize) -> Self {
Self {
header_tree: Tree {
nodes: Vec::with_capacity(size),
levels: Vec::new(),
},
node_index: Index {
inner: HashMap::with_capacity(size),
},
}
}
pub fn add(&mut self, header: DocumentBuilderHeader) -> super::Result<()> {
let id = header.id.ok_or(ConstraintError::MissingId)?;
let trace_id = header.trace_id.ok_or(ConstraintError::MissingTraceId)?;
let parent_id = header.parent_id;
let parent_node_id = parent_id.map(|parent_id| {
match self.node_index.get(&(trace_id, parent_id)).cloned() {
Some(parent_node_id) => {
parent_node_id
}
None => {
let parent_node_id = self
.header_tree
.insert_sorted(DocumentBuilderHeaderWrapper(None), None);
self.node_index
.insert((trace_id, parent_id), parent_node_id);
parent_node_id
}
}
});
match self.node_index.get(&(trace_id, id)).cloned() {
Some(node_id) => {
self.header_tree
.set_node_data(node_id, DocumentBuilderHeaderWrapper(Some(header)));
if let Some(parent_node_id) = parent_node_id {
self.header_tree.reparent_sorted(node_id, parent_node_id);
}
}
None => {
self.node_index.insert(
(trace_id, id),
self.header_tree
.insert_sorted(DocumentBuilderHeaderWrapper(Some(header)), parent_node_id),
);
}
};
Ok(())
}
pub fn iter(&self) -> DocumentBuilderHeaderTreeIterator<'_> {
DocumentBuilderHeaderTreeIterator {
tree: &self.header_tree,
current_level: self.header_tree.levels.len() - 1,
last_node_yield: None,
}
}
}
#[derive(Debug)]
pub(super) struct DocumentBuilderHeaderTreeIterator<'a> {
tree: &'a Tree<DocumentBuilderHeaderWrapper>,
current_level: usize,
last_node_yield: Option<NodeId>,
}
impl Iterator for DocumentBuilderHeaderTreeIterator<'_> {
type Item = DocumentBuilderHeader;
fn next(&mut self) -> Option<Self::Item> {
loop {
let next_id = match self.last_node_yield {
Some(last_node_yield) => {
let last_node = self.tree.get(last_node_yield);
if let Some(sibling) = last_node.next_sibling {
sibling
} else if let Some(cousin) = last_node.next_cousin {
cousin
} else if self.current_level > 0 {
self.current_level -= 1;
self.tree.levels[self.current_level].first
} else {
break None;
}
}
None => {
self.tree.levels[self.current_level].first
}
};
self.last_node_yield = Some(next_id);
if let Some(header) = self.tree.get(next_id).data.0 {
break Some(header);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn create_test_header(
id: u64,
parent_id: Option<u64>,
trace_id: u128,
start_time: f64,
end_time: f64,
) -> DocumentBuilderHeader {
DocumentBuilderHeader {
id: Some(Id::from(id)),
parent_id: parent_id.map(Id::from),
trace_id: Some(TraceId::from(trace_id)),
start_time: Some(start_time),
end_time: Some(end_time),
}
}
fn verify_tree_invariants<T: core::fmt::Debug + Ord>(tree: &Tree<T>) {
dbg!(&tree);
for node_id in 0..tree.nodes.len() {
let node = tree.get(NodeId(node_id));
if let Some(next_sibling) = node.next_sibling {
assert_eq!(
tree.get(next_sibling).previous_sibling,
Some(NodeId(node_id)),
"Sibling chain broken: next_sibling's previous_sibling doesn't point back"
);
}
if let Some(previous_sibling) = node.previous_sibling {
assert_eq!(
tree.get(previous_sibling).next_sibling,
Some(NodeId(node_id)),
"Sibling chain broken: previous_sibling's next_sibling doesn't point back"
);
}
if let Some(next_cousin) = node.next_cousin {
assert_eq!(
tree.get(next_cousin).previous_cousin,
Some(NodeId(node_id)),
"Cousin chain broken: next_cousin's previous_cousin doesn't point back"
);
}
if let Some(previous_cousin) = node.previous_cousin {
assert_eq!(
tree.get(previous_cousin).next_cousin,
Some(NodeId(node_id)),
"Cousin chain broken: previous_cousin's next_cousin doesn't point back"
);
}
}
for (level, TreeLevel { first, last }) in tree.levels.iter().enumerate() {
let first_node = tree.get(*first);
let last_node = tree.get(*last);
assert_eq!(first_node.level, level, "Level first node has wrong level");
assert_eq!(last_node.level, level, "Level last node has wrong level");
assert!(
first_node.previous_cousin.is_none(),
"Level first node should have no previous_cousin"
);
assert!(
last_node.next_cousin.is_none(),
"Level last node should have no next_cousin"
);
}
for node_id in 0..tree.nodes.len() {
let node = tree.get(NodeId(node_id));
if let Some(first_child) = node.first_child {
let mut sibling_cursor = first_child;
loop {
let child = tree.get(sibling_cursor);
assert_eq!(
child.level,
node.level + 1,
"Child level should be parent level + 1"
);
if let Some(next) = child.next_sibling {
sibling_cursor = next;
} else {
break;
}
}
}
}
}
fn assert_sibling_order<T: core::fmt::Debug + Ord>(tree: &Tree<T>, parent_id: NodeId) {
let parent = tree.get(parent_id);
if let Some(first_child) = parent.first_child {
let mut current = first_child;
let mut prev_data: Option<&T> = None;
loop {
let node = tree.get(current);
if let Some(prev) = prev_data {
assert!(
node.data >= *prev,
"Siblings not sorted: {:?} < {:?}",
node.data,
prev
);
}
prev_data = Some(&node.data);
if let Some(next) = node.next_sibling {
current = next;
} else {
break;
}
}
}
}
#[test]
fn test_tree_insert_root_node() {
let mut tree: Tree<u16> = Tree {
nodes: Vec::new(),
levels: Vec::new(),
};
let node_id = tree.insert_sorted(0, None);
assert_eq!(node_id, NodeId(0));
assert_eq!(tree.nodes.len(), 1);
assert_eq!(tree.get(node_id).level, 0);
assert_eq!(tree.levels.len(), 1);
assert_eq!(tree.levels[0].first, node_id);
assert_eq!(tree.levels[0].last, node_id);
verify_tree_invariants(&tree);
}
#[test]
fn test_tree_insert_child_node() {
let mut tree: Tree<u16> = Tree {
nodes: Vec::new(),
levels: Vec::new(),
};
let root_id = tree.insert_sorted(0, None);
let child_id = tree.insert_sorted(1, Some(root_id));
assert_eq!(child_id, NodeId(1));
assert_eq!(tree.nodes.len(), 2);
assert_eq!(tree.get(child_id).level, 1);
assert_eq!(tree.get(root_id).first_child, Some(child_id));
assert_eq!(tree.get(root_id).last_child, Some(child_id));
verify_tree_invariants(&tree);
}
#[test]
fn test_tree_insert_multiple_children() {
let mut tree: Tree<u16> = Tree {
nodes: Vec::new(),
levels: Vec::new(),
};
let root_id = tree.insert_sorted(0, None);
let _child1_id = tree.insert_sorted(3, Some(root_id));
let child2_id = tree.insert_sorted(2, Some(root_id));
let child3_id = tree.insert_sorted(4, Some(root_id));
assert_eq!(tree.nodes.len(), 4);
assert_sibling_order(&tree, root_id);
assert_eq!(tree.get(root_id).first_child, Some(child2_id));
assert_eq!(tree.get(root_id).last_child, Some(child3_id));
verify_tree_invariants(&tree);
}
#[test]
fn test_tree_set_node_data_only() {
let mut tree: Tree<u16> = Tree {
nodes: Vec::new(),
levels: Vec::new(),
};
let node_id = tree.insert_sorted(0, None);
tree.set_node_data(node_id, 1);
assert_eq!(tree.get(node_id).data, 1);
assert_eq!(tree.get(node_id).level, 0);
verify_tree_invariants(&tree);
}
fn insert_tree(
tree: &mut Tree<u16>,
start_id: u16,
node_count: usize,
max_depth: usize,
max_siblings: usize,
) {
let mut sibling_at_level: Vec<usize> = vec![];
let mut parents: Vec<NodeId> = vec![];
let mut inserted_count = 0;
let mut next_id = start_id;
loop {
loop {
let level = parents.len();
let siblings_sum = if let Some(sum) = sibling_at_level.get_mut(level) {
*sum += 1;
*sum
} else {
sibling_at_level.push(1);
1
};
if siblings_sum > max_siblings {
parents.pop();
sibling_at_level.pop();
if parents.is_empty() {
break;
}
} else {
break;
}
}
if sibling_at_level.is_empty() && parents.is_empty() {
break;
}
if inserted_count >= node_count {
break;
}
let parent_id = parents.last().cloned();
let node_id = tree.insert_sorted(next_id, parent_id);
inserted_count += 1;
if parents.len() < max_depth {
parents.push(node_id);
}
next_id += 1;
}
}
#[test]
fn test_tree_reparenting_single_node() {
let mut tree: Tree<u16> = Tree {
nodes: Vec::new(),
levels: Vec::new(),
};
insert_tree(&mut tree, 0, 4, 1, 3);
let root_id = NodeId(0);
let child_id = NodeId(2);
let node_id = tree.insert_sorted(4, None);
tree.reparent_sorted(node_id, root_id);
verify_tree_invariants(&tree);
tree.reparent_sorted(node_id, child_id);
verify_tree_invariants(&tree);
}
fn reparenting_subtrees(subtree_insertion: impl FnOnce(&mut Tree<u16>) -> NodeId) {
let mut tree: Tree<u16> = Tree {
nodes: Vec::new(),
levels: Vec::new(),
};
insert_tree(&mut tree, 0, 6, 2, 3);
let root_id = NodeId(0);
let child_id = NodeId(2);
let tree_head_id = subtree_insertion(&mut tree);
tree.reparent_sorted(tree_head_id, root_id);
verify_tree_invariants(&tree);
tree.reparent_sorted(tree_head_id, child_id);
verify_tree_invariants(&tree);
}
#[test]
fn test_tree_reparenting_subtrees() {
reparenting_subtrees(|tree| {
insert_tree(tree, 6, 4, 1, 3);
NodeId(6)
});
}
#[test]
fn test_tree_reparenting_bigger_subtree() {
reparenting_subtrees(|tree| {
insert_tree(tree, 6, 8, 3, 3);
NodeId(6)
});
}
#[test]
fn test_document_builder_header_tree_add_root_span() {
let mut tree = DocumentBuilderHeaderTree::new(10);
let header = create_test_header(1, None, 1, 1.0, 2.0);
let result = tree.add(header);
assert!(result.is_ok());
assert!(tree
.node_index
.get(&(TraceId::from(1), Id::from(1)))
.is_some());
assert_eq!(tree.header_tree.nodes.len(), 1);
assert_eq!(tree.header_tree.levels.len(), 1);
verify_tree_invariants(&tree.header_tree);
}
#[test]
fn test_document_builder_header_tree_add_with_known_parent() {
let mut tree = DocumentBuilderHeaderTree::new(10);
let parent = create_test_header(1, None, 1, 1.0, 2.0);
tree.add(parent).unwrap();
let child = create_test_header(2, Some(1), 1, 2.0, 3.0);
let result = tree.add(child);
assert!(result.is_ok());
assert!(tree
.node_index
.get(&(TraceId::from(1), Id::from(1)))
.is_some());
assert!(tree
.node_index
.get(&(TraceId::from(1), Id::from(2)))
.is_some());
assert_eq!(tree.header_tree.nodes.len(), 2);
assert_eq!(tree.header_tree.levels.len(), 2);
verify_tree_invariants(&tree.header_tree);
}
#[test]
fn test_document_builder_header_tree_add_with_unknown_parent() {
let mut tree = DocumentBuilderHeaderTree::new(10);
let child = create_test_header(2, Some(1), 1, 2.0, 3.0);
let result = tree.add(child);
assert!(result.is_ok());
let parent_node_id = tree.node_index.get(&(TraceId::from(1), Id::from(1)));
assert!(parent_node_id.is_some());
let parent_node = tree.header_tree.get(*parent_node_id.unwrap());
assert!(parent_node.data.0.is_none());
let child_node_id = tree.node_index.get(&(TraceId::from(1), Id::from(2)));
let child_node = tree.header_tree.get(*child_node_id.unwrap());
assert!(child_node.data.0.is_some());
verify_tree_invariants(&tree.header_tree);
}
#[test]
fn test_document_builder_header_tree_add_fill_placeholder() {
let mut tree = DocumentBuilderHeaderTree::new(10);
let child = create_test_header(2, Some(1), 1, 2.0, 3.0);
tree.add(child).unwrap();
let parent = create_test_header(1, None, 1, 1.0, 2.0);
let result = tree.add(parent);
assert!(result.is_ok());
let parent_node_id = tree
.node_index
.get(&(TraceId::from(1), Id::from(1)))
.unwrap();
let parent_node = tree.header_tree.get(*parent_node_id);
assert!(parent_node.data.0.is_some());
assert_eq!(parent_node.data.0.as_ref().unwrap().id, Some(Id::from(1)));
verify_tree_invariants(&tree.header_tree);
}
#[test]
fn test_document_builder_header_tree_add_fill_placeholder_with_reparent() {
let mut tree = DocumentBuilderHeaderTree::new(10);
let child = create_test_header(2, Some(1), 1, 2.0, 3.0);
tree.add(child).unwrap();
let parent_placeholder = tree.node_index.get(&(TraceId::from(1), Id::from(1)));
assert!(parent_placeholder.is_some());
let parent = create_test_header(1, None, 1, 1.0, 2.0);
let result = tree.add(parent);
assert!(result.is_ok());
let parent_node_id = tree
.node_index
.get(&(TraceId::from(1), Id::from(1)))
.unwrap();
let parent_node = tree.header_tree.get(*parent_node_id);
assert!(parent_node.data.0.is_some());
assert_eq!(parent_node.data.0.as_ref().unwrap().id, Some(Id::from(1)));
let child_node_id = tree.node_index.get(&(TraceId::from(1), Id::from(2)));
assert!(child_node_id.is_some());
verify_tree_invariants(&tree.header_tree);
}
#[test]
fn test_document_builder_header_tree_add_missing_id() {
let mut tree = DocumentBuilderHeaderTree::new(10);
let header = DocumentBuilderHeader {
id: None,
parent_id: None,
trace_id: Some(TraceId::from(1)),
start_time: Some(1.0),
end_time: Some(2.0),
};
let result = tree.add(header);
assert!(result.is_err());
}
#[test]
fn test_document_builder_header_tree_add_missing_trace_id() {
let mut tree = DocumentBuilderHeaderTree::new(10);
let header = DocumentBuilderHeader {
id: Some(Id::from(1)),
parent_id: None,
trace_id: None,
start_time: Some(1.0),
end_time: Some(2.0),
};
let result = tree.add(header);
assert!(result.is_err());
}
#[test]
fn test_iterator_empty_tree() {
let tree = DocumentBuilderHeaderTree::new(10);
assert_eq!(tree.header_tree.nodes.len(), 0);
assert_eq!(tree.header_tree.levels.len(), 0);
}
#[test]
fn test_iterator_single_root() {
let mut tree = DocumentBuilderHeaderTree::new(10);
let header = create_test_header(1, None, 1, 1.0, 2.0);
tree.add(header).unwrap();
let mut iter = tree.iter();
let result = iter.next();
assert!(result.is_some());
assert_eq!(result.unwrap().id, Some(Id::from(1)));
assert!(iter.next().is_none());
}
#[test]
fn test_iterator_multiple_roots() {
let mut tree = DocumentBuilderHeaderTree::new(10);
tree.add(create_test_header(1, None, 1, 2.0, 3.0)).unwrap();
tree.add(create_test_header(2, None, 1, 1.0, 2.0)).unwrap();
tree.add(create_test_header(3, None, 1, 3.0, 4.0)).unwrap();
let mut iter = tree.iter();
let first = iter.next().unwrap();
assert_eq!(first.id, Some(Id::from(1)));
let second = iter.next().unwrap();
assert_eq!(second.id, Some(Id::from(2)));
let third = iter.next().unwrap();
assert_eq!(third.id, Some(Id::from(3)));
assert!(iter.next().is_none());
}
#[test]
fn test_iterator_three_levels_bottom_up() {
let mut tree = DocumentBuilderHeaderTree::new(10);
tree.add(create_test_header(1, None, 1, 1.0, 2.0)).unwrap();
tree.add(create_test_header(2, Some(1), 1, 2.0, 3.0))
.unwrap();
tree.add(create_test_header(3, Some(2), 1, 3.0, 4.0))
.unwrap();
let mut iter = tree.iter();
let first = iter.next().unwrap();
assert_eq!(first.id, Some(Id::from(3)));
let second = iter.next().unwrap();
assert_eq!(second.id, Some(Id::from(2)));
let third = iter.next().unwrap();
assert_eq!(third.id, Some(Id::from(1)));
assert!(iter.next().is_none());
}
#[test]
fn test_iterator_siblings_chronological_order() {
let mut tree = DocumentBuilderHeaderTree::new(10);
tree.add(create_test_header(1, None, 1, 1.0, 2.0)).unwrap();
tree.add(create_test_header(2, Some(1), 1, 3.0, 4.0))
.unwrap();
tree.add(create_test_header(3, Some(1), 1, 2.0, 3.0))
.unwrap();
tree.add(create_test_header(4, Some(1), 1, 4.0, 5.0))
.unwrap();
let mut iter = tree.iter();
let first = iter.next().unwrap();
assert_eq!(first.id, Some(Id::from(3)));
let second = iter.next().unwrap();
assert_eq!(second.id, Some(Id::from(2)));
let third = iter.next().unwrap();
assert_eq!(third.id, Some(Id::from(4)));
let fourth = iter.next().unwrap();
assert_eq!(fourth.id, Some(Id::from(1)));
assert!(iter.next().is_none());
}
#[test]
fn test_iterator_skips_placeholders() {
let mut tree = DocumentBuilderHeaderTree::new(10);
tree.add(create_test_header(2, Some(1), 1, 2.0, 3.0))
.unwrap();
let mut iter = tree.iter();
let first = iter.next().unwrap();
assert_eq!(first.id, Some(Id::from(2)));
assert!(iter.next().is_none());
}
#[test]
fn test_iterator_complex_tree() {
let headers = [
create_test_header(1, None, 1, 1.0, 5.0),
create_test_header(2, Some(1), 1, 1.0, 2.0),
create_test_header(3, Some(1), 1, 2.0, 4.0),
create_test_header(4, Some(3), 1, 2.1, 3.0),
create_test_header(5, Some(3), 1, 3.0, 3.9),
create_test_header(6, Some(1), 1, 4.0, 5.0),
create_test_header(7, Some(6), 1, 4.1, 4.9),
create_test_header(8, None, 2, 4.0, 4.5),
];
struct CombinationIterator {
picked: [usize; 8],
availables: [bool; 8],
end_reached: bool,
}
impl CombinationIterator {
fn new() -> Self {
Self {
picked: [0, 1, 2, 3, 4, 5, 6, 7],
availables: [false; 8],
end_reached: false,
}
}
}
impl Iterator for CombinationIterator {
type Item = [usize; 8];
fn next(&mut self) -> Option<Self::Item> {
let Self {
picked,
availables,
end_reached,
} = self;
if *end_reached {
None
} else {
let next = Some(*picked);
let mut cursor = picked.len() - 1;
let made_progress = loop {
let p = picked[cursor];
if let Some((index, _)) =
availables.iter().enumerate().skip(p + 1).find(|(_, b)| **b)
{
availables[p] = true;
picked[cursor] = index;
availables[index] = false;
cursor += 1;
break true;
} else {
availables[p] = true;
if cursor > 0 {
cursor -= 1;
} else {
break false;
}
}
};
if made_progress {
while cursor < picked.len() {
let index = availables.iter().position(|b| *b).unwrap();
picked[cursor] = index;
availables[index] = false;
cursor += 1;
}
} else {
*end_reached = true;
}
next
}
}
}
let mut test_count = 0usize;
for indexes in CombinationIterator::new() {
test_count += 1;
let mut tree = DocumentBuilderHeaderTree::new(8);
for i in indexes {
tree.add(headers[i]).unwrap();
}
let mut expect = None;
let mut expect_grand_children = true;
let mut expect_root = false;
let mut count = 0usize;
fn is_grand_child(header: DocumentBuilderHeader) -> bool {
[Id::from(4), Id::from(5), Id::from(7)].contains(&header.id.unwrap())
}
fn is_root(header: DocumentBuilderHeader) -> bool {
[Id::from(1), Id::from(8)].contains(&header.id.unwrap())
}
fn is_id(header: DocumentBuilderHeader, id: u64) -> bool {
header.id == Some(Id::from(id))
}
fn assert_id(header: DocumentBuilderHeader, id: u64) {
assert!(is_id(header, id), "Should have been Id({id})");
}
for header in tree.iter() {
assert!(
!expect_grand_children || is_grand_child(header),
"Should have been a grandchild"
);
assert!(
!expect_root || is_root(header),
"Should have been a grandchild"
);
if let Some(id) = expect {
assert_id(header, id);
}
count += 1;
if count == 6 {
expect_root = true;
}
expect = if is_id(header, 4) {
Some(5)
} else if is_id(header, 2) {
Some(3)
} else if is_id(header, 3) {
Some(6)
} else if count == 3 {
expect_grand_children = false;
Some(2)
} else {
None
};
}
assert_eq!(count, 8, "Iterator did not yield all the nodes");
}
dbg!(test_count);
}
}