#![allow(unused_variables)]
use std::collections::HashMap;
use interstellar::p;
use interstellar::storage::Graph;
use interstellar::traversal::__;
use interstellar::value::Value;
use crate::common::graphs::{create_empty_graph, create_property_test_graph, create_small_graph};
#[test]
fn empty_graph_v_returns_empty_list() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().to_list();
assert!(results.is_empty());
}
#[test]
fn empty_graph_e_returns_empty_list() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.e().to_list();
assert!(results.is_empty());
}
#[test]
fn empty_graph_count_returns_zero() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
assert_eq!(g.v().count(), 0);
assert_eq!(g.e().count(), 0);
}
#[test]
fn empty_graph_out_returns_empty() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().out().to_list();
assert!(results.is_empty());
}
#[test]
fn empty_graph_values_returns_empty() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().values("name").to_list();
assert!(results.is_empty());
}
#[test]
fn filter_removes_all_vertices() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().has_value("name", "NonexistentPerson").to_list();
assert!(results.is_empty());
}
#[test]
fn filter_removes_all_then_chained_steps() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_value("name", "NonexistentPerson")
.out()
.values("name")
.to_list();
assert!(results.is_empty());
}
#[test]
fn empty_traversal_in_where_filters_all() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g
.v()
.has_label("person")
.where_(__.out_labels(&["manages"]))
.to_list();
assert!(results.is_empty());
}
#[test]
fn empty_start_with_v_ids_nonexistent() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g.v_ids([interstellar::value::VertexId(99999)]).to_list();
assert!(results.is_empty());
}
#[test]
fn empty_navigation_chain() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g.v_ids([tg.graphdb]).out().to_list();
assert!(results.is_empty());
let results = g.v_ids([tg.graphdb]).out().out().out().to_list();
assert!(results.is_empty());
}
#[test]
fn empty_dedup_on_empty_traversal() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().dedup().to_list();
assert!(results.is_empty());
}
#[test]
fn empty_limit_on_empty_traversal() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().limit(10).to_list();
assert!(results.is_empty());
}
#[test]
fn empty_traversal_sum_returns_zero() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let result = g.v().values("age").sum();
assert_eq!(result, Value::Int(0));
}
#[test]
fn empty_traversal_min_returns_none() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let result = g.v().values("age").min();
assert!(result.is_none());
}
#[test]
fn empty_traversal_max_returns_none() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let result = g.v().values("age").max();
assert!(result.is_none());
}
#[test]
fn empty_traversal_next_returns_none() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
assert!(g.v().next().is_none());
}
#[test]
fn empty_traversal_has_next_returns_false() {
let graph = create_empty_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
assert!(!g.v().has_next());
}
#[test]
fn single_vertex_one_succeeds() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let result = g.v_ids([tg.alice]).one();
assert!(result.is_ok());
assert_eq!(result.unwrap().as_vertex_id(), Some(tg.alice));
}
#[test]
fn single_vertex_after_filter_one_succeeds() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let result = g.v().has_value("name", "Alice").one();
assert!(result.is_ok());
}
#[test]
fn one_fails_on_multiple_results() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let result = g.v().has_label("person").one();
assert!(result.is_err());
}
#[test]
fn one_fails_on_empty_results() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let result = g.v().has_value("name", "Nobody").one();
assert!(result.is_err());
}
#[test]
fn single_element_min_max_equal() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let min = g.v_ids([tg.alice]).values("age").min();
let max = g.v_ids([tg.alice]).values("age").max();
assert!(min.is_some());
assert!(max.is_some());
assert_eq!(min, max); }
#[test]
fn single_element_count_is_one() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
assert_eq!(g.v_ids([tg.alice]).count(), 1);
}
#[test]
fn single_element_dedup_unchanged() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g.v_ids([tg.alice]).dedup().to_list();
assert_eq!(results.len(), 1);
assert_eq!(results[0].as_vertex_id(), Some(tg.alice));
}
#[test]
fn single_element_limit_larger_than_one() {
let tg = create_small_graph();
let snapshot = tg.graph.snapshot();
let g = snapshot.gremlin();
let results = g.v_ids([tg.alice]).limit(10).to_list();
assert_eq!(results.len(), 1);
}
#[test]
fn values_skips_vertices_without_property() {
let graph = Graph::new();
let v1 = graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("A".to_string()));
props
});
let v2 = graph.add_vertex("test", HashMap::new());
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let names = g.v().values("name").to_list();
assert_eq!(names.len(), 1);
assert_eq!(names[0], Value::String("A".to_string()));
}
#[test]
fn has_property_filters_out_missing() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("A".to_string()));
props
});
graph.add_vertex("test", HashMap::new()); graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("C".to_string()));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let with_name = g.v().has("name").to_list();
assert_eq!(with_name.len(), 2);
}
#[test]
fn has_value_filters_out_missing_property() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("Alice".to_string()));
props
});
graph.add_vertex("test", HashMap::new());
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().has_value("name", "Alice").to_list();
assert_eq!(results.len(), 1);
}
#[test]
fn has_where_on_missing_property() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("age".to_string(), Value::Int(30));
props
});
graph.add_vertex("test", HashMap::new());
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().has_where("age", p::gt(20)).to_list();
assert_eq!(results.len(), 1);
}
#[test]
fn multiple_properties_some_missing() {
let graph = Graph::new();
graph.add_vertex("person", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("Alice".to_string()));
props.insert("age".to_string(), Value::Int(30));
props
});
graph.add_vertex("person", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("Bob".to_string()));
props
});
graph.add_vertex("person", {
let mut props = HashMap::new();
props.insert("age".to_string(), Value::Int(25));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let with_both = g.v().has("name").has("age").to_list();
assert_eq!(with_both.len(), 1);
let names = g.v().values("name").to_list();
assert_eq!(names.len(), 2);
let ages = g.v().values("age").to_list();
assert_eq!(ages.len(), 2);
}
#[test]
fn aggregation_on_partially_missing_properties() {
let graph = Graph::new();
graph.add_vertex("person", {
let mut props = HashMap::new();
props.insert("age".to_string(), Value::Int(30));
props
});
graph.add_vertex("person", HashMap::new()); graph.add_vertex("person", {
let mut props = HashMap::new();
props.insert("age".to_string(), Value::Int(20));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let sum = g.v().values("age").sum();
assert_eq!(sum, Value::Int(50));
let min = g.v().values("age").min();
assert_eq!(min, Some(Value::Int(20)));
let max = g.v().values("age").max();
assert_eq!(max, Some(Value::Int(30)));
}
#[test]
fn order_by_missing_property() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("B".to_string()));
props.insert("priority".to_string(), Value::Int(2));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("A".to_string()));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("C".to_string()));
props.insert("priority".to_string(), Value::Int(1));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().values("priority").order().by_asc().build().to_list();
assert_eq!(results.len(), 2);
}
#[test]
fn mixed_int_float_sum() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Int(10));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Float(5.5));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Int(20));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let result = g.v().values("value").sum();
if let Value::Float(f) = result {
assert!((f - 35.5).abs() < 1e-10);
} else {
panic!("Expected Float for mixed sum, got {:?}", result);
}
}
#[test]
fn mixed_int_float_min() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Int(10));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Float(5.5));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Int(20));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let result = g.v().values("value").min();
assert!(result.is_some());
assert_eq!(result, Some(Value::Int(10)));
}
#[test]
fn mixed_int_float_max() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Int(10));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Float(25.5));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Int(20));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let result = g.v().values("value").max();
assert!(result.is_some());
if let Some(Value::Float(f)) = result {
assert!((f - 25.5).abs() < 1e-10);
} else {
panic!("Expected Float maximum, got {:?}", result);
}
}
#[test]
fn int_comparison_with_int_predicate() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Int(42));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Int(10));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().has_where("value", p::eq(42i64)).to_list();
assert_eq!(results.len(), 1);
let results = g.v().has_where("value", p::gt(30i64)).to_list();
assert_eq!(results.len(), 1);
}
#[test]
fn string_comparison_exact_match() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("Alice".to_string()));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("name".to_string(), Value::String("Bob".to_string()));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let results = g.v().has_value("name", "Alice").to_list();
assert_eq!(results.len(), 1);
let results = g.v().has_value("name", "Charlie").to_list();
assert!(results.is_empty());
}
#[test]
fn bool_property_filtering() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("active".to_string(), Value::Bool(true));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("active".to_string(), Value::Bool(false));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let active = g.v().has_value("active", true).to_list();
assert_eq!(active.len(), 1);
let inactive = g.v().has_value("active", false).to_list();
assert_eq!(inactive.len(), 1);
}
#[test]
fn null_property_handling() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Null);
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Int(42));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let with_value = g.v().has("value").to_list();
assert_eq!(with_value.len(), 2);
let values = g.v().values("value").to_list();
assert_eq!(values.len(), 2);
}
#[test]
fn type_mismatch_in_predicate() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::String("42".to_string()));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("value".to_string(), Value::Int(42));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let int_results = g.v().has_where("value", p::eq(42i64)).to_list();
assert_eq!(int_results.len(), 1);
}
#[test]
fn ordering_mixed_numeric_types() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("score".to_string(), Value::Int(10));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("score".to_string(), Value::Float(5.5));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("score".to_string(), Value::Int(20));
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("score".to_string(), Value::Float(15.0));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let ordered = g.v().values("score").order().by_asc().build().to_list();
assert_eq!(ordered.len(), 4);
assert_eq!(ordered[0], Value::Int(10));
assert_eq!(ordered[1], Value::Int(20));
if let Value::Float(f) = ordered[2] {
assert!((f - 5.5).abs() < 1e-10);
} else {
panic!("Expected Float at index 2, got {:?}", ordered[2]);
}
if let Value::Float(f) = ordered[3] {
assert!((f - 15.0).abs() < 1e-10);
} else {
panic!("Expected Float at index 3, got {:?}", ordered[3]);
}
}
#[test]
fn list_property_handling() {
let graph = Graph::new();
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert(
"tags".to_string(),
Value::List(vec![
Value::String("rust".to_string()),
Value::String("graph".to_string()),
]),
);
props
});
graph.add_vertex("test", {
let mut props = HashMap::new();
props.insert("tags".to_string(), Value::List(vec![]));
props
});
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let with_tags = g.v().has("tags").to_list();
assert_eq!(with_tags.len(), 2);
let tags = g.v().values("tags").to_list();
assert_eq!(tags.len(), 2);
}
#[test]
fn property_test_graph_all_vertex_types() {
let graph = create_property_test_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let vertex_count = g.v().count();
assert_eq!(vertex_count, 6);
let complete = g.v().has_label("complete").count();
let strings_only = g.v().has_label("strings_only").count();
let numbers_only = g.v().has_label("numbers_only").count();
let booleans = g.v().has_label("booleans").count();
let sparse = g.v().has_label("sparse").count();
let nested = g.v().has_label("nested").count();
assert_eq!(complete, 1);
assert_eq!(strings_only, 1);
assert_eq!(numbers_only, 1);
assert_eq!(booleans, 1);
assert_eq!(sparse, 1);
assert_eq!(nested, 1);
}
#[test]
fn property_test_graph_string_properties() {
let graph = create_property_test_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let names = g.v().has_label("strings_only").values("name").to_list();
assert_eq!(names.len(), 1);
assert_eq!(names[0], Value::String("StringVertex".to_string()));
let empty = g
.v()
.has_label("strings_only")
.values("empty_string")
.to_list();
assert_eq!(empty.len(), 1);
assert_eq!(empty[0], Value::String("".to_string()));
let unicode = g.v().has_label("strings_only").values("unicode").to_list();
assert_eq!(unicode.len(), 1);
assert_eq!(unicode[0], Value::String("こんにちは 🌍".to_string()));
}
#[test]
fn property_test_graph_numeric_edge_cases() {
let graph = create_property_test_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let large_int = g
.v()
.has_label("numbers_only")
.values("large_int")
.to_list();
assert_eq!(large_int.len(), 1);
assert_eq!(large_int[0], Value::Int(i64::MAX));
let small_int = g
.v()
.has_label("numbers_only")
.values("small_int")
.to_list();
assert_eq!(small_int.len(), 1);
assert_eq!(small_int[0], Value::Int(i64::MIN));
let zero = g.v().has_label("numbers_only").values("zero").to_list();
assert_eq!(zero.len(), 1);
assert_eq!(zero[0], Value::Int(0));
let tiny = g
.v()
.has_label("numbers_only")
.values("tiny_float")
.to_list();
assert_eq!(tiny.len(), 1);
if let Value::Float(f) = tiny[0] {
assert!((f - 0.000001).abs() < 1e-12);
} else {
panic!("Expected Float, got {:?}", tiny[0]);
}
}
#[test]
fn property_test_graph_boolean_filtering() {
let graph = create_property_test_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let active = g
.v()
.has_label("booleans")
.has_value("is_active", true)
.count();
assert_eq!(active, 1);
let deleted = g
.v()
.has_label("booleans")
.has_value("is_deleted", false)
.count();
assert_eq!(deleted, 1);
}
#[test]
fn property_test_graph_null_property_exists() {
let graph = create_property_test_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let nulls = g.v().has_label("sparse").values("null_value").to_list();
assert_eq!(nulls.len(), 1);
assert_eq!(nulls[0], Value::Null);
let with_null = g.v().has_label("sparse").has("null_value").count();
assert_eq!(with_null, 1);
}
#[test]
fn property_test_graph_list_property() {
let graph = create_property_test_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let list = g.v().has_label("complete").values("list_prop").to_list();
assert_eq!(list.len(), 1);
if let Value::List(items) = &list[0] {
assert_eq!(items.len(), 3);
assert_eq!(items[0], Value::Int(1));
assert_eq!(items[1], Value::Int(2));
assert_eq!(items[2], Value::Int(3));
} else {
panic!("Expected List, got {:?}", list[0]);
}
}
#[test]
fn property_test_graph_map_property() {
let graph = create_property_test_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let map = g.v().has_label("complete").values("map_prop").to_list();
assert_eq!(map.len(), 1);
if let Value::Map(m) = &map[0] {
assert!(m.contains_key("nested_key"));
assert_eq!(
m.get("nested_key"),
Some(&Value::String("nested_value".to_string()))
);
} else {
panic!("Expected Map, got {:?}", map[0]);
}
}
#[test]
fn property_test_graph_cross_label_property_query() {
let graph = create_property_test_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let int_prop_count = g.v().has("int_prop").count();
assert_eq!(int_prop_count, 1);
let with_name = g.v().has("name").count();
assert_eq!(with_name, 1); }
#[test]
fn property_test_graph_sparse_vs_complete() {
let graph = create_property_test_graph();
let snapshot = graph.snapshot();
let g = snapshot.gremlin();
let complete_props = g
.v()
.has_label("complete")
.has("string_prop")
.has("int_prop")
.has("float_prop")
.has("bool_prop")
.count();
assert_eq!(complete_props, 1);
let sparse_has_int = g.v().has_label("sparse").has("int_prop").count();
assert_eq!(sparse_has_int, 0);
let sparse_has_string = g.v().has_label("sparse").has("string_prop").count();
assert_eq!(sparse_has_string, 0);
}