//! API Compatibility Tests for scirs2-graph
//!
//! This test suite verifies that stable APIs remain unchanged between versions.
//! Any breaking changes to these tests indicate API compatibility issues.
#![allow(dead_code)]
#![allow(unused_variables)]
use scirs2_graph::algorithms::{
dijkstra_path, label_propagation, louvain_communities, shortest_path,
};
use scirs2_graph::*;
use std::collections::HashMap;
/// Test core graph types remain stable
#[test]
#[allow(dead_code)]
fn test_core_graph_types_stable() {
// Core graph construction should remain stable
let graph = Graph::<usize, f64>::new();
let digraph = DiGraph::<usize, f64>::new();
let multigraph = MultiGraph::<usize, f64>::new();
let multi_digraph = MultiDiGraph::<usize, f64>::new();
// Bipartite graph construction
let bipartite = BipartiteGraph::<usize, f64>::new();
// Basic operations should remain stable
assert_eq!(graph.node_count(), 0);
assert_eq!(graph.edge_count(), 0);
}
/// Test core algorithm signatures remain stable
#[test]
#[allow(dead_code)]
fn test_traversal_algorithms_stable() {
let mut graph = Graph::new();
graph.add_node(0).unwrap();
graph.add_node(1).unwrap();
graph.add_edge(0, 1, 1.0).unwrap();
// These function signatures must not change
let _bfs_result = breadth_first_search(&graph, &0);
let _dfs_result = depth_first_search(&graph, &0);
let _bidirectional_result = bidirectional_search(&graph, &0, &1);
}
/// Test shortest path algorithms remain stable
#[test]
#[allow(dead_code)]
fn test_shortest_path_algorithms_stable() {
let mut graph = Graph::new();
graph.add_node(0).unwrap();
graph.add_node(1).unwrap();
graph.add_edge(0, 1, 2.0).unwrap();
// Stable API - should not change
let _dijkstra_result = dijkstra_path(&graph, &0, &1);
let _floyd_result = floyd_warshall(&graph);
let _k_paths_result = k_shortest_paths(&graph, &0, &1, 5);
}
/// Test connectivity algorithms remain stable
#[test]
#[allow(dead_code)]
fn test_connectivity_algorithms_stable() {
let mut graph = Graph::new();
for i in 0..5 {
graph.add_node(i).unwrap();
}
graph.add_edge(0, 1, 1.0).unwrap();
graph.add_edge(1, 2, 1.0).unwrap();
graph.add_edge(3, 4, 1.0).unwrap();
// These functions should maintain their signatures
let _components = connected_components(&graph);
let _articulation = articulation_points(&graph);
let _bridges = bridges(&graph);
}
/// Test centrality algorithms remain stable
#[test]
#[allow(dead_code)]
fn test_centrality_algorithms_stable() {
let mut graph = Graph::new();
for i in 0..4 {
graph.add_node(i).unwrap();
if i > 0 {
graph.add_edge(0, i, 1.0).unwrap(); // Star graph
}
}
// Centrality measure signatures should be stable
let _betweenness = betweenness_centrality(&graph);
let _closeness = closeness_centrality(&graph);
let _eigenvector = eigenvector_centrality(&graph, None, None);
// PageRank variations should be stable
let _pagerank = pagerank(&graph, None, None, None);
let _personalized = personalized_pagerank(&graph, &HashMap::new(), None, None, None);
}
/// Test community detection result types remain stable
#[test]
#[allow(dead_code)]
fn test_community_detection_stable() {
let mut graph = Graph::new();
for i in 0..6 {
graph.add_node(i).unwrap();
}
// Create two communities
graph.add_edge(0, 1, 1.0).unwrap();
graph.add_edge(1, 2, 1.0).unwrap();
graph.add_edge(3, 4, 1.0).unwrap();
graph.add_edge(4, 5, 1.0).unwrap();
graph.add_edge(2, 3, 0.1).unwrap(); // Weak connection
// Result-based API should be stable
let _louvain_result: CommunityResult = louvain_communities_result(&graph, None, None);
let _label_prop_result: CommunityResult = label_propagation_result(&graph, None, None);
let _fluid_result: CommunityResult = fluid_communities_result(&graph, 2, None, None);
// Modularity function should be stable
let communities = vec![vec![0, 1, 2], vec![3, 4, 5]];
let _modularity_score = modularity(&graph, &communities);
}
/// Test graph generators remain stable
#[test]
#[allow(dead_code)]
fn test_graph_generators_stable() {
use rand::rngs::StdRng;
use rand::SeedableRng;
let mut rng = StdRng::seed_from_u64(42);
// Generator function signatures should not change
let _erdos = erdos_renyi_graph(100, 0.05, &mut rng).unwrap();
let _barabasi = barabasi_albert_graph(100, 3, &mut rng).unwrap();
let _watts = watts_strogatz_graph(100, 4, 0.3, &mut rng).unwrap();
let _complete = complete_graph(10);
let _star = star_graph(10);
let _cycle = cycle_graph(10);
let _path = path_graph(10);
}
/// Test graph measures remain stable
#[test]
#[allow(dead_code)]
fn test_graph_measures_stable() {
let mut graph = Graph::new();
for i in 0..5 {
graph.add_node(i).unwrap();
if i > 0 {
graph.add_edge(i - 1, i, 1.0).unwrap();
}
}
// Measure function signatures should be stable
let _density = graph_density(&graph);
let _clustering = clustering_coefficient(&graph);
// HITS algorithm should be stable
let _hits_scores: HitsScores = hits_algorithm(&graph, None, None);
// Katz centrality should be stable
let _katz = katz_centrality(&graph, None, None, None);
}
/// Test error types remain stable
#[test]
#[allow(dead_code)]
fn test_error_types_stable() {
// Error type should maintain its structure
let error = GraphError::node_not_found(42);
let _result: Result<()> = Err(error);
// Error context should be stable
let _context = ErrorContext::new("test operation");
}
/// Test graph I/O remains stable
#[test]
#[allow(dead_code)]
fn test_io_stability() {
use std::io::Cursor;
let graph = complete_graph(5);
// I/O function signatures should not change
let mut buffer = Vec::new();
let cursor = Cursor::new(&mut buffer);
// These functions should maintain compatibility
// Note: Actual file I/O tested separately to avoid file system dependencies
let _json_str = serde_json::to_string(&graph);
}
/// Test attribute system remains stable
#[test]
#[allow(dead_code)]
fn test_attribute_system_stable() {
let mut graph = AttributedGraph::<usize, f64>::new();
// Basic attributed graph operations should be stable
graph.add_node_with_attributes(0, Attributes::new());
// Attribute operations should maintain their API
let attributes = Attributes::new();
// let _summary = attributes.summarize();
}
/// Test weighted operations remain stable
#[test]
#[allow(dead_code)]
fn test_weighted_operations_stable() {
let mut graph = Graph::new();
graph.add_node(0);
graph.add_node(1);
graph.add_edge(0, 1, 2.5).unwrap();
// Weighted operations API should be stable
// let weighted_ops = WeightedOps::new(&graph);
// let _stats = weighted_ops.weight_statistics();
}
/// Test result type compatibility
#[test]
#[allow(dead_code)]
fn test_result_types_stable() {
// Result types should maintain their structure
let _community_result = CommunityResult {
node_communities: HashMap::new(),
num_communities: 0,
quality_score: 0.0,
};
let _astar_result = AStarResult {
path: vec![],
cost: 0.0,
};
let _bipartite_result = BipartiteResult {
coloring: HashMap::new(),
};
}
/// Test that deprecated functions still work but issue warnings
#[test]
#[allow(deprecated)]
#[allow(dead_code)]
fn test_deprecated_functions_compatibility() {
let graph = complete_graph(5);
// These should work but generate deprecation warnings
let _shortest = dijkstra_path(&graph, &0, &1);
let _louvain = louvain_communities(&graph);
let _label_prop = label_propagation(&graph);
}
/// Test parallel feature compatibility
#[cfg(feature = "parallel")]
#[test]
#[allow(dead_code)]
fn test_parallel_api_stable() {
let graph = complete_graph(100);
// Parallel APIs should maintain compatibility
let _parallel_pagerank = parallel_pagerank_centrality(&graph, None, None, None);
let _parallel_louvain = parallel_louvain_communities_result(&graph, None, None);
}
/// Test experimental features are properly gated
#[cfg(feature = "experimental")]
#[test]
#[allow(dead_code)]
fn test_experimental_features_gated() {
let graph1 = complete_graph(5);
let graph2 = cycle_graph(5);
// Experimental features should be available only with feature flag
let _isomorphic = are_graphs_isomorphic(&graph1, &graph2);
let _edit_distance = graph_edit_distance(&graph1, &graph2);
}
/// Test Advanced API stability (experimental but stable interface)
#[test]
#[allow(dead_code)]
fn test_advanced_api_stable() {
let graph = complete_graph(10);
// Advanced processor creation should be stable
let _processor = create_advanced_processor();
// Basic Advanced configuration should be stable
let _config = AdvancedConfig::default();
}
/// Compile-time API signature verification
/// This test ensures function signatures haven't changed
#[test]
#[allow(dead_code)]
fn test_compile_time_signatures() {
// This test will fail to compile if signatures change
fn verify_bfs_signature() -> fn(&Graph<usize, f64>, &usize) -> Result<Vec<usize>> {
breadth_first_search
}
fn verify_dijkstra_signature() -> fn(&Graph<usize, f64>, &usize, &usize) -> Result<Vec<usize>> {
dijkstra_path
}
fn verify_louvain_signature(
) -> fn(&Graph<usize, f64>, Option<f64>, Option<usize>) -> CommunityResult {
louvain_communities_result
}
// These functions should compile, proving signatures are correct
let _bfs_fn = verify_bfs_signature();
let _dijkstra_fn = verify_dijkstra_signature();
let _louvain_fn = verify_louvain_signature();
}