mod common;
use common::*;
use anyhow::Result;
use wolf_graph::prelude::*;
#[test]
fn test_is_tree() {
let graph = make_graph();
assert!(!graph.is_tree(nid!("A")));
let dag = make_dag();
assert!(!dag.is_tree(nid!("A")));
let tree = make_tree();
assert!(tree.is_tree(nid!("A")));
let mut g = BlankGraph::new();
fn is_a_tree(g: &BlankGraph) {
assert!(g.is_tree(nid!("root")));
}
fn is_not_a_tree(g: &BlankGraph, root: NodeID) {
assert!(!g.is_tree(root));
}
is_not_a_tree(&g, nid!("root"));
g.add_node(nid!("root")).unwrap();
is_a_tree(&g);
g.add_node(nid!("A")).unwrap();
is_not_a_tree(&g, nid!("root"));
g.add_edge(eid!("rA"), nid!("root"), nid!("A")).unwrap();
is_a_tree(&g);
g.add_node(nid!("B")).unwrap();
g.add_edge(eid!("rB"), nid!("root"), nid!("B")).unwrap();
is_a_tree(&g);
is_not_a_tree(&g, nid!("A"));
g.add_node(nid!("C")).unwrap();
g.add_node(nid!("D")).unwrap();
g.add_node(nid!("E")).unwrap();
g.add_node(nid!("F")).unwrap();
g.add_edge(eid!("AC"), nid!("A"), nid!("C")).unwrap();
g.add_edge(eid!("AD"), nid!("A"), nid!("D")).unwrap();
g.add_edge(eid!("BE"), nid!("B"), nid!("E")).unwrap();
g.add_edge(eid!("BF"), nid!("B"), nid!("F")).unwrap();
is_a_tree(&g);
let undo = g.clone();
g.add_edge(eid!("CE"), nid!("C"), nid!("E")).unwrap();
is_not_a_tree(&g, nid!("root"));
g = undo.clone();
is_a_tree(&g);
g.add_edge(eid!("Cr"), nid!("C"), nid!("root")).unwrap();
is_not_a_tree(&g, nid!("root"));
g = undo.clone();
is_a_tree(&g);
g.add_edge(eid!("BE2"), nid!("B"), nid!("E")).unwrap();
is_not_a_tree(&g, nid!("root"));
g = undo;
is_a_tree(&g);
}
fn make_test_tree() -> BlankTree {
Tree::new_with_root_and_graph(nid!("A"), make_tree()).unwrap()
}
#[test]
fn test_tree_codable() -> Result<()> {
let tree = make_test_tree();
recode(&tree, r#"["A",[["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O"],[["AB","A","B"],["AC","A","C"],["AD","A","D"],["BI","B","I"],["CH","C","H"],["DE","D","E"],["DF","D","F"],["DG","D","G"],["EM","E","M"],["EN","E","N"],["EO","E","O"],["FL","F","L"],["HJ","H","J"],["HK","H","K"]]]]"#)?;
Ok(())
}
#[test]
fn test_creation_1() -> Result<()> {
let mut t1 = BlankTree::new();
t1.add_node(nid!("A"), None::<NodeID>, eid!("rA"))?;
t1.add_node(nid!("B"), None::<NodeID>, eid!("rB"))?;
assert_eq!(t1, t1);
recode(&t1, r#"["root",[["A","B","root"],[["rA","root","A"],["rB","root","B"]]]]"#)?;
let mut t2 = Tree::<Graph<String, (), ()>>::new()
.setting_data("graphData".to_string());
t2.add_node(nid!("A"), None::<NodeID>, eid!("rA"))?;
t2.add_node(nid!("B"), None::<NodeID>, eid!("rB"))?;
assert_eq!(t2, t2);
recode(&t2, r#"["root",[["A","B","root"],[["rA","root","A"],["rB","root","B"]],"graphData"]]"#)?;
let mut t3 = Tree::<Graph<(), String, ()>>::new()
.setting_node_data(nid!("root"), "rootData".to_string())?;
t3.add_node_with_node_data(nid!("A"), None::<NodeID>, eid!("rA"), "aNodeData".to_string())?;
t3.add_node_with_node_data(nid!("B"), None::<NodeID>, eid!("rB"), "bNodeData".to_string())?;
assert_eq!(t3, t3);
recode(&t3, r#"["root",[[["A","aNodeData"],["B","bNodeData"],["root","rootData"]],[["rA","root","A"],["rB","root","B"]]]]"#)?;
let mut t4 = Tree::<Graph<(), (), String>>::new();
t4.add_node_with_edge_data(nid!("A"), None::<NodeID>, eid!("rA"), "raEdgeData".to_string())?;
t4.add_node_with_edge_data(nid!("B"), None::<NodeID>, eid!("rB"), "rbEdgeData".to_string())?;
assert_eq!(t4, t4);
recode(&t4, r#"["root",[["A","B","root"],[["rA","root","A","raEdgeData"],["rB","root","B","rbEdgeData"]]]]"#)?;
let mut t5 = Tree::<Graph<String, (), String>>::new()
.setting_data("graphData".to_string());
t5.add_node_with_edge_data(nid!("A"), None::<NodeID>, eid!("rA"), "raEdgeData".to_string())?;
t5.add_node_with_edge_data(nid!("B"), None::<NodeID>, eid!("rB"), "rbEdgeData".to_string())?;
assert_eq!(t5, t5);
recode(&t5, r#"["root",[["A","B","root"],[["rA","root","A","raEdgeData"],["rB","root","B","rbEdgeData"]],"graphData"]]"#)?;
let mut t6 = Tree::<Graph<(), String, String>>::new();
t6.add_node_with_node_and_edge_data(nid!("A"), None::<NodeID>, eid!("rA"), "aNodeData".to_string(), "raEdgeData".to_string())?;
t6.add_node_with_node_and_edge_data(nid!("B"), None::<NodeID>, eid!("rB"), "bNodeData".to_string(), "rbEdgeData".to_string())?;
assert_eq!(t6, t6);
recode(&t6, r#"["root",[[["A","aNodeData"],["B","bNodeData"],["root",""]],[["rA","root","A","raEdgeData"],["rB","root","B","rbEdgeData"]]]]"#)?;
let mut t7 = Tree::<Graph<String, String, ()>>::new()
.setting_data("graphData".to_string())
.setting_node_data(nid!("root"), "rootData".to_string())?;
t7.add_node_with_node_data(nid!("A"), None::<NodeID>, eid!("rA"), "aNodeData".to_string())?;
t7.add_node_with_node_data(nid!("B"), None::<NodeID>, eid!("rB"), "bNodeData".to_string())?;
assert_eq!(t7, t7);
recode(&t7, r#"["root",[[["A","aNodeData"],["B","bNodeData"],["root","rootData"]],[["rA","root","A"],["rB","root","B"]],"graphData"]]"#)?;
let mut t8 = Tree::<Graph<String, String, String>>::new()
.setting_data("graphData".to_string())
.setting_node_data(nid!("root"), "rootData".to_string())?;
t8.add_node_with_node_and_edge_data(nid!("A"), None::<NodeID>, eid!("rA"), "aNodeData".to_string(), "raEdgeData".to_string())?;
t8.add_node_with_node_and_edge_data(nid!("B"), None::<NodeID>, eid!("rB"), "bNodeData".to_string(), "rbEdgeData".to_string())?;
assert_eq!(t8, t8);
recode(&t8, r#"["root",[[["A","aNodeData"],["B","bNodeData"],["root","rootData"]],[["rA","root","A","raEdgeData"],["rB","root","B","rbEdgeData"]],"graphData"]]"#)?;
Ok(())
}
#[test]
fn test_tree_queries() -> Result<()> {
let root_only_tree = BlankTree::new();
assert!(!root_only_tree.is_empty());
let t = make_test_tree();
assert!(!t.is_empty());
assert_eq!(t.node_count(), 15);
assert_eq!(t.edge_count(), 14);
assert_eq!(format_ids(t.all_nodes()), "[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O]");
assert_eq!(format_ids(t.all_edges()), "[AB, AC, AD, BI, CH, DE, DF, DG, EM, EN, EO, FL, HJ, HK]");
assert!(t.has_node(nid!("F")));
assert!(!t.has_node(nid!("Z")));
assert!(t.has_edge(eid!("CH")));
assert!(!t.has_edge(eid!("ZZ")));
assert!(t.has_edge_from_to(nid!("A"), nid!("C")));
assert!(!t.has_edge_from_to(nid!("E"), nid!("A")));
assert!(t.has_edge_between(nid!("A"), nid!("D")));
assert!(t.has_edge_between(nid!("D"), nid!("F")));
assert_eq!(t.source(eid!("DE"))?, nid!("D"));
assert_eq!(t.target(eid!("DE"))?, nid!("E"));
assert_eq!(t.endpoints(eid!("CH"))?, (nid!("C"), nid!("H")));
assert_eq!(format_ids(t.out_edges(nid!("E"))?), "[EM, EN, EO]");
assert_eq!(format_ids(t.in_edges(nid!("E"))?), "[DE]");
assert_eq!(format_ids(t.incident_edges(nid!("A"))?), "[AB, AC, AD]");
assert_eq!(t.out_degree(nid!("E"))?, 3);
assert_eq!(t.in_degree(nid!("E"))?, 1);
assert_eq!(t.degree(nid!("E"))?, 4);
assert_eq!(format_ids(t.successors(nid!("D"))?), "[E, F, G]");
assert_eq!(format_ids(t.predecessors(nid!("D"))?), "[A]");
assert_eq!(format_ids(t.neighbors(nid!("E"))?), "[D, M, N, O]");
assert_eq!(format_ids(t.all_roots()), "[A]");
assert_eq!(format_ids(t.non_roots()), "[B, C, D, E, F, G, H, I, J, K, L, M, N, O]");
assert_eq!(format_ids(t.all_leaves()), "[G, I, J, K, L, M, N, O]");
assert_eq!(format_ids(t.all_internals()), "[B, C, D, E, F, H]");
assert!(t.is_leaf(nid!("K"))?);
assert!(!t.is_leaf(nid!("H"))?);
assert!(t.is_root(nid!("A"))?);
assert!(!t.is_root(nid!("H"))?);
assert!(t.is_internal(nid!("C"))?);
assert!(!t.is_internal(nid!("A"))?);
assert!(!t.is_internal(nid!("K"))?);
assert_eq!(t.root(), nid!("A"));
assert_eq!(t.in_edge(nid!("H"))?, Some(eid!("CH")));
assert_eq!(t.in_edge(nid!("A"))?, None);
assert_eq!(t.parent(nid!("H"))?, Some(nid!("C")));
assert_eq!(t.parent(nid!("A"))?, None);
assert_eq!(format_ids(t.children(Some(nid!("H")))?), "[J, K]");
assert!(t.has_children(nid!("H"))?);
assert!(!t.has_children(nid!("K"))?);
Ok(())
}
#[test]
fn test_tree_mutations() -> Result<()> {
let mut t = BlankTree::new();
assert_eq!(t, t);
recode(&t, r#"["root",[["root"],[]]]"#)?;
assert_eq!(format_ids(t.all_roots()), "[root]");
assert_eq!(format_ids(t.all_leaves()), "[root]");
t.add_node(nid!("A"), None::<NodeID>, eid!("rA"))?;
t.add_node(nid!("B"), None::<NodeID>, eid!("rB"))?;
recode(&t, r#"["root",[["A","B","root"],[["rA","root","A"],["rB","root","B"]]]]"#)?;
assert_eq!(format_ids(t.all_leaves()), "[A, B]");
t.add_node(nid!("C"), Some(nid!("A")), eid!("AC"))?;
t.add_node(nid!("D"), Some(nid!("A")), eid!("AD"))?;
t.add_node(nid!("E"), Some(nid!("B")), eid!("BE"))?;
t.add_node(nid!("F"), Some(nid!("B")), eid!("BF"))?;
recode(&t, r#"["root",[["A","B","C","D","E","F","root"],[["AC","A","C"],["AD","A","D"],["BE","B","E"],["BF","B","F"],["rA","root","A"],["rB","root","B"]]]]"#)?;
assert_eq!(format_ids(t.all_leaves()), "[C, D, E, F]");
let undo = t.clone();
t.remove_node_ungrouping(nid!("A"))?;
recode(&t, r#"["root",[["B","C","D","E","F","root"],[["AC","root","C"],["AD","root","D"],["BE","B","E"],["BF","B","F"],["rB","root","B"]]]]"#)?;
assert_eq!(format_ids(t.all_leaves()), "[C, D, E, F]");
t.remove_node_and_children(nid!("B"))?;
recode(&t, r#"["root",[["C","D","root"],[["AC","root","C"],["AD","root","D"]]]]"#)?;
assert_eq!(format_ids(t.all_leaves()), "[C, D]");
t = undo.clone();
recode(&t, r#"["root",[["A","B","C","D","E","F","root"],[["AC","A","C"],["AD","A","D"],["BE","B","E"],["BF","B","F"],["rA","root","A"],["rB","root","B"]]]]"#)?;
assert_eq!(format_ids(t.all_leaves()), "[C, D, E, F]");
t = undo.clone();
t.remove_children(nid!("B"))?;
recode(&t, r#"["root",[["A","B","C","D","root"],[["AC","A","C"],["AD","A","D"],["rA","root","A"],["rB","root","B"]]]]"#)?;
assert_eq!(format_ids(t.all_leaves()), "[B, C, D]");
t = undo;
t.move_node(nid!("B"), Some(nid!("D")))?;
recode(&t, r#"["root",[["A","B","C","D","E","F","root"],[["AC","A","C"],["AD","A","D"],["BE","B","E"],["BF","B","F"],["rA","root","A"],["rB","D","B"]]]]"#)?;
assert_eq!(format_ids(t.all_leaves()), "[C, E, F]");
Ok(())
}
#[test]
fn test_tree_builders() -> Result<()> {
let t1 = BlankTree::new();
recode(&t1, r#"["root",[["root"],[]]]"#)?;
assert_eq!(format_ids(t1.all_roots()), "[root]");
assert_eq!(format_ids(t1.all_leaves()), "[root]");
let t2 = t1
.adding_node(nid!("A"), None::<NodeID>, eid!("rA"))?
.adding_node(nid!("B"), None::<NodeID>, eid!("rB"))?;
recode(&t2, r#"["root",[["A","B","root"],[["rA","root","A"],["rB","root","B"]]]]"#)?;
assert_eq!(format_ids(t2.all_leaves()), "[A, B]");
let t3 = t2
.adding_node(nid!("C"), Some(nid!("A")), eid!("AC"))?
.adding_node(nid!("D"), Some(nid!("A")), eid!("AD"))?
.adding_node(nid!("E"), Some(nid!("B")), eid!("BE"))?
.adding_node(nid!("F"), Some(nid!("B")), eid!("BF"))?;
recode(&t3, r#"["root",[["A","B","C","D","E","F","root"],[["AC","A","C"],["AD","A","D"],["BE","B","E"],["BF","B","F"],["rA","root","A"],["rB","root","B"]]]]"#)?;
assert_eq!(format_ids(t3.all_leaves()), "[C, D, E, F]");
let t4 = t3.removing_node_ungrouping(nid!("A"))?;
recode(&t4, r#"["root",[["B","C","D","E","F","root"],[["AC","root","C"],["AD","root","D"],["BE","B","E"],["BF","B","F"],["rB","root","B"]]]]"#)?;
assert_eq!(format_ids(t4.all_leaves()), "[C, D, E, F]");
let t5 = t4.removing_node_and_children(nid!("B"))?;
recode(&t5, r#"["root",[["C","D","root"],[["AC","root","C"],["AD","root","D"]]]]"#)?;
assert_eq!(format_ids(t5.all_leaves()), "[C, D]");
let t6 = t3.moving_node(nid!("B"), Some(nid!("D")))?;
recode(&t6, r#"["root",[["A","B","C","D","E","F","root"],[["AC","A","C"],["AD","A","D"],["BE","B","E"],["BF","B","F"],["rA","root","A"],["rB","D","B"]]]]"#)?;
assert_eq!(format_ids(t6.all_leaves()), "[C, E, F]");
Ok(())
}
#[test]
fn test_with_data() -> Result<()> {
let mut t = Tree::<Graph<TestElemData, TestElemData, TestElemData>>::new();
recode(&t, r#"["root",[[["root",[0,""]]],[],[0,""]]]"#)?;
t.with_data(&|data| {
data.0 = 10;
data.1 = "dog".to_string();
});
recode(&t, r#"["root",[[["root",[0,""]]],[],[10,"dog"]]]"#)?;
assert_eq!(*t.data(), TestElemData(10, "dog".to_string()));
t.with_data(&|data| {
data.0 = 20;
data.1 = "cat".to_string();
});
recode(&t, r#"["root",[[["root",[0,""]]],[],[20,"cat"]]]"#)?;
t.add_node_with_node_and_edge_data(nid!("A"), Some(nid!("root")), eid!("rA"), TestElemData(1, "ape".to_string()), TestElemData(2, "bat".to_string()))?;
t.add_node(nid!("B"), Some(nid!("root")), eid!("rC"))?;
recode(&t, r#"["root",[[["A",[1,"ape"]],["B",[0,""]],["root",[0,""]]],[["rA","root","A",[2,"bat"]],["rC","root","B",[0,""]]],[20,"cat"]]]"#)?;
t.with_node_data(nid!("A"), &|data| {
data.0 = 30;
data.1 = "elephant".to_string();
})?;
assert_eq!(t.node_data(nid!("A"))?.into_owned(), TestElemData(30, "elephant".to_string()));
t.with_edge_data(eid!("rA"), &|data| {
data.0 = 40;
data.1 = "fox".to_string();
})?;
assert_eq!(t.edge_data(eid!("rA"))?.into_owned(), TestElemData(40, "fox".to_string()));
recode(&t, r#"["root",[[["A",[30,"elephant"]],["B",[0,""]],["root",[0,""]]],[["rA","root","A",[40,"fox"]],["rC","root","B",[0,""]]],[20,"cat"]]]"#)?;
Ok(())
}