use super::*;
use crate::tui::graph_analytics::{GraphAnalytics, GraphAnalyticsExt};
#[test]
fn test_pagerank_empty_graph() {
let graph: Graph<(), ()> = Graph::new();
let ranks = GraphAnalytics::pagerank(&graph, 0.85, 20);
assert!(ranks.is_empty());
}
#[test]
fn test_pagerank_single_node() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("solo", ()));
let ranks = GraphAnalytics::pagerank(&graph, 0.85, 20);
assert_eq!(ranks.len(), 1);
assert!((ranks.get("solo").unwrap() - 1.0).abs() < 0.01);
}
#[test]
fn test_pagerank_linear_chain() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("A", ()));
graph.add_node(Node::new("B", ()));
graph.add_node(Node::new("C", ()));
graph.add_edge(Edge::new("A", "B", ()));
graph.add_edge(Edge::new("B", "C", ()));
let ranks = GraphAnalytics::pagerank(&graph, 0.85, 50);
let rank_a = *ranks.get("A").unwrap();
let rank_b = *ranks.get("B").unwrap();
let rank_c = *ranks.get("C").unwrap();
assert!(rank_c > rank_b, "C should rank higher than B");
assert!(rank_b > rank_a, "B should rank higher than A");
}
#[test]
fn test_pagerank_cycle() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("A", ()));
graph.add_node(Node::new("B", ()));
graph.add_node(Node::new("C", ()));
graph.add_edge(Edge::new("A", "B", ()));
graph.add_edge(Edge::new("B", "C", ()));
graph.add_edge(Edge::new("C", "A", ()));
let ranks = GraphAnalytics::pagerank(&graph, 0.85, 50);
let rank_a = *ranks.get("A").unwrap();
let rank_b = *ranks.get("B").unwrap();
let rank_c = *ranks.get("C").unwrap();
assert!((rank_a - rank_b).abs() < 0.1);
assert!((rank_b - rank_c).abs() < 0.1);
}
#[test]
fn test_pagerank_star_topology() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("center", ()));
graph.add_node(Node::new("A", ()));
graph.add_node(Node::new("B", ()));
graph.add_node(Node::new("C", ()));
graph.add_node(Node::new("D", ()));
graph.add_edge(Edge::new("center", "A", ()));
graph.add_edge(Edge::new("center", "B", ()));
graph.add_edge(Edge::new("center", "C", ()));
graph.add_edge(Edge::new("center", "D", ()));
let ranks = GraphAnalytics::pagerank(&graph, 0.85, 50);
let rank_center = *ranks.get("center").unwrap();
let rank_a = *ranks.get("A").unwrap();
assert!(rank_a > rank_center, "Leaf A should rank higher than center");
}
#[test]
fn test_apply_pagerank() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("A", ()));
graph.add_node(Node::new("B", ()));
graph.add_edge(Edge::new("A", "B", ()));
assert_eq!(graph.get_node("A").unwrap().importance, 1.0);
GraphAnalytics::apply_pagerank(&mut graph, 0.85, 20);
let imp_a = graph.get_node("A").unwrap().importance;
let imp_b = graph.get_node("B").unwrap().importance;
assert!(imp_b > imp_a, "B should have higher importance after PageRank");
}
#[test]
fn test_community_empty_graph() {
let graph: Graph<(), ()> = Graph::new();
let communities = GraphAnalytics::detect_communities(&graph);
assert!(communities.is_empty());
}
#[test]
fn test_community_single_node() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("solo", ()));
let communities = GraphAnalytics::detect_communities(&graph);
assert_eq!(communities.len(), 1);
assert_eq!(*communities.get("solo").unwrap(), 0);
}
#[test]
fn test_community_two_clusters() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("A", ()));
graph.add_node(Node::new("B", ()));
graph.add_node(Node::new("C", ()));
graph.add_edge(Edge::new("A", "B", ()));
graph.add_edge(Edge::new("B", "C", ()));
graph.add_edge(Edge::new("C", "A", ()));
let communities = GraphAnalytics::detect_communities(&graph);
assert_eq!(communities.len(), 3);
let max_comm = *communities.values().max().unwrap();
assert!(max_comm < 3, "Should have at most 3 communities for 3 nodes");
}
#[test]
fn test_community_colors() {
for i in 0..10 {
let color = GraphAnalytics::community_color(i);
assert!(color.starts_with("\x1b["), "Should be ANSI escape code");
assert!(color.ends_with('m'), "Should end with 'm'");
}
}
#[test]
fn test_apply_communities() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("A", ()));
graph.add_node(Node::new("B", ()));
graph.add_node(Node::new("C", ()));
graph.add_edge(Edge::new("A", "B", ()));
graph.add_edge(Edge::new("B", "C", ()));
let num_communities = GraphAnalytics::apply_communities(&mut graph);
assert!(num_communities >= 1);
let imp_a = graph.get_node("A").unwrap().importance;
assert!((0.0..=1.0).contains(&imp_a));
}
#[test]
fn test_analytics_ext_trait() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("A", ()));
graph.add_node(Node::new("B", ()));
graph.add_edge(Edge::new("A", "B", ()));
let scores = graph.pagerank_scores();
assert_eq!(scores.len(), 2);
graph.compute_pagerank(0.85, 10);
let num_comm = graph.detect_communities();
assert!(num_comm >= 1);
}
#[test]
fn test_degree_centrality() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("center", ()));
for i in 0..4 {
graph.add_node(Node::new(format!("n{}", i), ()));
graph.add_edge(Edge::new("center", format!("n{}", i), ()));
}
let degrees = GraphAnalytics::degree_centrality(&graph);
let center_deg = *degrees.get("center").unwrap();
for i in 0..4 {
let leaf_deg = *degrees.get(&format!("n{}", i)).unwrap();
assert!(center_deg > leaf_deg, "Center should have highest degree centrality");
}
}
#[test]
fn test_betweenness_centrality() {
let mut graph: Graph<(), ()> = Graph::new();
for c in ['A', 'B', 'C', 'D'] {
graph.add_node(Node::new(c.to_string(), ()));
}
graph.add_edge(Edge::new("A", "B", ()));
graph.add_edge(Edge::new("B", "C", ()));
graph.add_edge(Edge::new("C", "D", ()));
let betweenness = GraphAnalytics::betweenness_centrality(&graph);
let b_between = *betweenness.get("B").unwrap();
let a_between = *betweenness.get("A").unwrap();
assert!(b_between >= a_between, "Middle nodes should have higher betweenness");
}
#[test]
fn test_closeness_centrality() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("center", ()));
for i in 0..4 {
graph.add_node(Node::new(format!("n{}", i), ()));
graph.add_edge(Edge::new("center", format!("n{}", i), ()));
}
let closeness = GraphAnalytics::closeness_centrality(&graph);
let center_close = *closeness.get("center").unwrap();
assert!(center_close > 0.0, "Center should have positive closeness");
}
#[test]
fn test_shortest_path_exists() {
let mut graph: Graph<(), ()> = Graph::new();
for c in ['A', 'B', 'C', 'D'] {
graph.add_node(Node::new(c.to_string(), ()));
}
graph.add_edge(Edge::new("A", "B", ()));
graph.add_edge(Edge::new("B", "C", ()));
graph.add_edge(Edge::new("C", "D", ()));
let path = GraphAnalytics::shortest_path(&graph, "A", "D");
assert!(path.is_some());
let path = path.unwrap();
assert_eq!(path, vec!["A", "B", "C", "D"]);
}
#[test]
fn test_shortest_path_same_node() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("A", ()));
let path = GraphAnalytics::shortest_path(&graph, "A", "A");
assert!(path.is_some());
assert_eq!(path.unwrap(), vec!["A"]);
}
#[test]
fn test_shortest_path_no_path() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("A", ()));
graph.add_node(Node::new("B", ()));
let path = GraphAnalytics::shortest_path(&graph, "A", "B");
assert!(path.is_none());
}
#[test]
fn test_is_connected() {
let mut graph: Graph<(), ()> = Graph::new();
graph.add_node(Node::new("A", ()));
graph.add_node(Node::new("B", ()));
graph.add_edge(Edge::new("A", "B", ()));
assert!(GraphAnalytics::is_connected(&graph));
graph.add_node(Node::new("C", ()));
assert!(!GraphAnalytics::is_connected(&graph));
}