#![allow(unused_variables)]
use std::collections::HashMap;
use interstellar::p;
use interstellar::storage::Graph;
use interstellar::traversal::__;
use interstellar::value::{Value, VertexId};
use crate::common::graphs::{
create_dense_graph, create_medium_graph, create_small_graph, create_social_graph,
};
#[test]
fn six_step_navigation_chain() {
let tg = create_social_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v_ids([tg.alice])
.out_labels(&["knows"]) .out_labels(&["knows"]) .out_labels(&["knows"]) .out_labels(&["knows"]) .out_labels(&["knows"]) .out_labels(&["knows"]) .dedup()
.to_list();
assert!(!results.is_empty());
assert!(results.len() <= 3); }
#[test]
fn deep_out_in_alternating_chain() {
let tg = create_social_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v_ids([tg.alice])
.out_labels(&["knows"]) .in_labels(&["knows"]) .out_labels(&["knows"]) .in_labels(&["knows"]) .out_labels(&["knows"]) .dedup()
.to_list();
assert!(!results.is_empty());
}
#[test]
fn deep_bidirectional_exploration() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v_ids([tg.bob])
.both_labels(&["knows"]) .both_labels(&["knows"]) .both_labels(&["knows"]) .dedup()
.to_list();
let ids: Vec<VertexId> = results.iter().filter_map(|v| v.as_vertex_id()).collect();
assert!(ids.contains(&tg.alice) || ids.contains(&tg.bob) || ids.contains(&tg.charlie));
}
#[test]
fn deep_chain_with_multiple_labels() {
let tg = create_social_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v_ids([tg.alice])
.out_labels(&["knows"]) .out_labels(&["created"]) .in_labels(&["uses"]) .out_labels(&["uses"]) .in_labels(&["created"]) .to_list();
let _ = results;
}
#[test]
fn deep_chain_terminates_on_dead_end() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v_ids([tg.graphdb])
.out() .out() .out() .out() .to_list();
assert!(results.is_empty());
}
#[test]
fn deep_chain_with_limit_at_end() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v_ids([tg.alice])
.repeat(__.out_labels(&["knows"]))
.times(5)
.emit()
.dedup()
.limit(2)
.to_list();
assert!(results.len() <= 2);
}
#[test]
fn filter_navigation_transform_chain() {
let tg = create_social_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person") .has_where("age", p::gte(25i64)) .out_labels(&["knows"]) .has_label("person") .values("name") .to_list();
for result in &results {
assert!(result.as_str().is_some());
}
}
#[test]
fn navigation_filter_aggregate_chain() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let count = g
.v_ids([tg.alice])
.out() .has_label("person") .out() .dedup() .count();
let _ = count; }
#[test]
fn transform_filter_navigation_chain() {
let tg = create_medium_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person")
.as_("person") .values("age") .as_("age") .select_one("person") .out_labels(&["knows"]) .to_list();
assert!(!results.is_empty());
}
#[test]
fn predicate_chain_with_navigation() {
let tg = create_medium_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person")
.has_where("status", p::eq("active"))
.has_where("age", p::gt(20i64))
.out_labels(&["knows"])
.has_where("age", p::lt(40i64))
.to_list();
for result in &results {
if let Some(id) = result.as_vertex_id() {
let _ = id;
}
}
}
#[test]
fn dedup_limit_skip_chain() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v_ids([tg.alice])
.repeat(__.out_labels(&["knows"]))
.times(4)
.emit()
.dedup() .limit(10) .to_list();
let ids: Vec<VertexId> = results.iter().filter_map(|v| v.as_vertex_id()).collect();
let unique_count = ids.len();
let mut sorted = ids.clone();
sorted.sort();
sorted.dedup();
assert_eq!(sorted.len(), unique_count);
}
#[test]
fn order_limit_chain() {
let tg = create_medium_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person")
.values("age")
.order()
.by_asc()
.build()
.limit(2)
.to_list();
assert!(results.len() <= 2);
if results.len() == 2 {
let a = results[0].as_i64().unwrap_or(0);
let b = results[1].as_i64().unwrap_or(0);
assert!(a <= b);
}
}
#[test]
fn nested_where_clauses() {
let tg = create_social_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person")
.where_(
__.out_labels(&["knows"])
.where_(__.out_labels(&["created"]).has_label("software")),
)
.values("name")
.to_list();
assert!(!results.is_empty());
}
#[test]
fn nested_or_and_conditions() {
let tg = create_medium_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person")
.or_(vec![
__.has_where("age", p::lt(28i64)),
__.and_(vec![
__.has_where("status", p::eq("active")),
__.out_labels(&["knows"]),
]),
])
.to_list();
assert!(!results.is_empty());
}
#[test]
fn nested_choose_with_union() {
let tg = create_medium_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person")
.choose(
__.has_where("status", p::eq("active")),
__.union(vec![__.out_labels(&["knows"]), __.out_labels(&["created"])]),
__.constant(Value::String("inactive".to_string())),
)
.to_list();
assert!(!results.is_empty());
}
#[test]
fn nested_coalesce_chain() {
let tg = create_medium_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person")
.coalesce(vec![
__.values("nickname"),
__.values("name"),
__.constant(Value::String("unknown".to_string())),
])
.to_list();
assert_eq!(results.len(), 3); for result in &results {
assert!(result.as_str().is_some());
}
}
#[test]
fn deeply_nested_anonymous_filter() {
let tg = create_social_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person")
.where_(
__.out_labels(&["knows"])
.where_(__.out_labels(&["knows"]).where_(__.has_label("person"))),
)
.values("name")
.to_list();
assert!(!results.is_empty());
}
#[test]
fn anonymous_in_repeat() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v_ids([tg.alice])
.repeat(__.out_labels(&["knows"]).has_label("person"))
.times(3)
.emit()
.dedup()
.to_list();
assert!(!results.is_empty());
}
#[test]
fn friends_of_friends_pattern() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let fof = g
.v_ids([tg.alice])
.out_labels(&["knows"]) .out_labels(&["knows"]) .dedup()
.to_list();
assert!(!fof.is_empty());
let ids: Vec<VertexId> = fof.iter().filter_map(|v| v.as_vertex_id()).collect();
assert!(ids.contains(&tg.charlie));
}
#[test]
fn mutual_friends_pattern() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let alice_knows = g.v_ids([tg.alice]).out_labels(&["knows"]).to_list();
let charlie_knows = g.v_ids([tg.charlie]).out_labels(&["knows"]).to_list();
let alice_friend_ids: Vec<VertexId> = alice_knows
.iter()
.filter_map(|v| v.as_vertex_id())
.collect();
let charlie_friend_ids: Vec<VertexId> = charlie_knows
.iter()
.filter_map(|v| v.as_vertex_id())
.collect();
let mutual: Vec<VertexId> = alice_friend_ids
.iter()
.filter(|id| charlie_friend_ids.contains(id))
.copied()
.collect();
let _ = mutual;
}
#[test]
fn recommendation_pattern() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let recommendations = g
.v_ids([tg.alice])
.out_labels(&["knows"]) .out_labels(&["uses"]) .dedup()
.to_list();
for rec in &recommendations {
if let Some(id) = rec.as_vertex_id() {
assert_eq!(id, tg.graphdb);
}
}
}
#[test]
fn co_creation_pattern() {
let tg = create_social_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let co_creators = g
.v_ids([tg.alice])
.out_labels(&["created"]) .in_labels(&["created"]) .has_label("person")
.dedup()
.to_list();
let ids: Vec<VertexId> = co_creators
.iter()
.filter_map(|v| v.as_vertex_id())
.collect();
assert!(ids.len() <= 1);
}
#[test]
fn hierarchical_traversal_pattern() {
let graph = Graph::new();
let ceo = graph.add_vertex("employee", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("CEO".to_string()));
props.insert("level".to_string(), Value::Int(0));
props
});
let cto = graph.add_vertex("employee", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("CTO".to_string()));
props.insert("level".to_string(), Value::Int(1));
props
});
graph
.add_edge(cto, ceo, "reports_to", HashMap::new())
.unwrap();
let manager = graph.add_vertex("employee", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("Manager".to_string()));
props.insert("level".to_string(), Value::Int(2));
props
});
graph
.add_edge(manager, cto, "reports_to", HashMap::new())
.unwrap();
let dev = graph.add_vertex("employee", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("Developer".to_string()));
props.insert("level".to_string(), Value::Int(3));
props
});
graph
.add_edge(dev, manager, "reports_to", HashMap::new())
.unwrap();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let chain = g
.v_ids([dev])
.repeat(__.out_labels(&["reports_to"]))
.until(__.has_where("level", p::eq(0i64)))
.emit()
.values("name")
.to_list();
assert!(chain.len() >= 3 && chain.len() <= 4);
let names: Vec<&str> = chain.iter().filter_map(|v| v.as_str()).collect();
assert!(names.contains(&"Manager"));
assert!(names.contains(&"CTO"));
assert!(names.contains(&"CEO"));
}
#[test]
fn shortest_path_approximation() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let path = g
.v_ids([tg.alice])
.with_path()
.repeat(__.out_labels(&["knows"]))
.until(__.has_where("name", p::eq("Charlie")))
.limit(1)
.path()
.to_list();
if !path.is_empty() {
if let Value::List(p) = &path[0] {
assert!(p.len() >= 2); }
}
}
#[test]
fn degree_centrality_pattern() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let people = g.v().has_label("person").to_list();
for person in people {
if let Some(id) = person.as_vertex_id() {
let out_degree = g.v_ids([id]).out().count();
let in_degree = g.v_ids([id]).in_().count();
let total_degree = out_degree + in_degree;
assert!(total_degree > 0, "Person {:?} has no connections", id);
}
}
}
#[test]
fn find_isolated_vertices() {
let graph = Graph::new();
let connected1 = graph.add_vertex("node", HashMap::new());
let connected2 = graph.add_vertex("node", HashMap::new());
let isolated = graph.add_vertex("node", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("isolated".to_string()));
props
});
graph
.add_edge(connected1, connected2, "link", HashMap::new())
.unwrap();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let all_vertices = g.v().to_list();
let mut isolated_count = 0;
for vertex in &all_vertices {
if let Some(id) = vertex.as_vertex_id() {
let has_edges = g.v_ids([id]).both().has_next();
if !has_edges {
isolated_count += 1;
}
}
}
assert_eq!(isolated_count, 1); }
#[test]
fn property_statistics_query() {
let tg = create_medium_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let min_age = g.v().has_label("person").values("age").min();
let max_age = g.v().has_label("person").values("age").max();
let sum_age = g.v().has_label("person").values("age").sum();
let count = g.v().has_label("person").count();
assert!(min_age.is_some());
assert!(max_age.is_some());
let min = min_age.unwrap().as_i64().unwrap();
let max = max_age.unwrap().as_i64().unwrap();
assert!(min <= max);
assert!(sum_age.as_i64().unwrap_or(0) > 0);
assert!(count > 0);
}
#[test]
fn path_with_labeled_steps() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v_ids([tg.alice])
.as_("start")
.out_labels(&["knows"])
.as_("friend")
.out_labels(&["knows"])
.as_("fof")
.select(&["start", "friend", "fof"])
.to_list();
assert!(!results.is_empty());
for result in &results {
if let Value::Map(map) = result {
assert!(map.contains_key("start"));
assert!(map.contains_key("friend"));
assert!(map.contains_key("fof"));
}
}
}
#[test]
fn conditional_navigation_pattern() {
let tg = create_medium_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person")
.choose(
__.has_where("status", p::eq("active")),
__.out_labels(&["created"]),
__.out_labels(&["knows"]),
)
.to_list();
assert!(!results.is_empty());
}
#[test]
fn aggregation_after_complex_traversal() {
let tg = create_social_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let count = g
.v()
.has_label("person")
.where_(__.out_labels(&["knows"]))
.out_labels(&["knows"])
.out_labels(&["knows"])
.dedup()
.count();
let _ = count; }
#[test]
fn union_with_different_depths() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v_ids([tg.alice])
.union(vec![
__.out_labels(&["knows"]), __.out_labels(&["knows"]).out_labels(&["knows"]), ])
.dedup()
.to_list();
let ids: Vec<VertexId> = results.iter().filter_map(|v| v.as_vertex_id()).collect();
assert!(ids.contains(&tg.bob) || ids.contains(&tg.charlie));
}
#[test]
fn dense_graph_deep_navigation() {
let graph = create_dense_graph(50, 5);
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let vertex_count = g.v().count();
assert_eq!(vertex_count, 50);
let start_id = g
.v()
.has_where("index", p::eq(0i64))
.to_list()
.first()
.and_then(|v| v.as_vertex_id());
if let Some(id) = start_id {
let results = g
.v_ids([id])
.out_labels(&["connects"])
.out_labels(&["connects"])
.out_labels(&["connects"])
.out_labels(&["connects"])
.dedup()
.to_list();
assert!(!results.is_empty());
assert!(results.len() >= 10);
}
}
#[test]
fn dense_graph_repeat_with_dedup() {
let graph = create_dense_graph(30, 4);
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let start_id = g
.v()
.has_where("index", p::eq(0i64))
.to_list()
.first()
.and_then(|v| v.as_vertex_id());
if let Some(id) = start_id {
let results = g
.v_ids([id])
.repeat(__.out_labels(&["connects"]))
.times(5)
.emit()
.dedup()
.to_list();
assert!(results.len() >= 10);
assert!(results.len() <= 30);
}
}
#[test]
fn dense_graph_bidirectional_exploration() {
let graph = create_dense_graph(40, 3);
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let start_id = g
.v()
.has_where("index", p::eq(20i64))
.to_list()
.first()
.and_then(|v| v.as_vertex_id());
if let Some(id) = start_id {
let results = g
.v_ids([id])
.both_labels(&["connects"])
.both_labels(&["connects"])
.dedup()
.to_list();
assert!(!results.is_empty());
}
}
#[test]
fn dense_graph_filter_chain_on_properties() {
let graph = create_dense_graph(100, 5);
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_where("index", p::lt(10i64)) .out_labels(&["connects"])
.has_where("index", p::gte(50i64)) .dedup()
.to_list();
let _ = results; }
#[test]
fn dense_graph_weighted_edges() {
let graph = create_dense_graph(20, 4);
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let edges = g.e().to_list();
assert!(!edges.is_empty());
let edge_weights = g.e().values("weight").to_list();
assert!(!edge_weights.is_empty());
for weight in &edge_weights {
if let Value::Float(w) = weight {
assert!(*w > 0.0 && *w <= 1.0);
}
}
}
#[test]
fn dense_graph_complex_mixed_chain() {
let graph = create_dense_graph(50, 4);
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("node") .has_where("index", p::lte(5i64)) .out_labels(&["connects"]) .has_where("index", p::gt(10i64)) .out_labels(&["connects"]) .dedup()
.limit(20) .to_list();
assert!(results.len() <= 20);
}
#[test]
fn dense_graph_union_from_multiple_starts() {
let graph = create_dense_graph(30, 3);
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let vertices = g.v().has_where("index", p::lte(1i64)).to_list();
let ids: Vec<VertexId> = vertices.iter().filter_map(|v| v.as_vertex_id()).collect();
if ids.len() >= 2 {
let results = g
.v_ids(ids)
.union(vec![
__.out_labels(&["connects"]),
__.out_labels(&["connects"]).out_labels(&["connects"]),
])
.dedup()
.to_list();
assert!(!results.is_empty());
}
}
#[test]
fn dense_graph_count_reachable_vertices() {
let graph = create_dense_graph(50, 5);
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let start_id = g
.v()
.has_where("index", p::eq(0i64))
.to_list()
.first()
.and_then(|v| v.as_vertex_id());
if let Some(id) = start_id {
let reachable_count = g
.v_ids([id])
.repeat(__.out_labels(&["connects"]))
.times(3)
.emit()
.dedup()
.count();
assert!(reachable_count >= 15);
}
}