use crate::{Edge, Vertex, assert_elements_eq, populate_graph};
use graph_api_lib::{EdgeReference, EdgeSearch, Graph, VertexSearch};
pub fn test_boxed_simple<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let refs = populate_graph(graph);
let unboxed_result = graph
.walk()
.vertices_by_id(vec![refs.bryn])
.edges(EdgeSearch::scan().outgoing())
.head()
.collect::<Vec<_>>();
let boxed_result = graph
.walk()
.vertices_by_id(vec![refs.bryn])
.edges(EdgeSearch::scan().outgoing())
.boxed() .head()
.collect::<Vec<_>>();
assert_elements_eq!(
graph,
unboxed_result.clone(),
vec![refs.graph_api, refs.julia]
);
assert_elements_eq!(graph, boxed_result, vec![refs.graph_api, refs.julia]);
}
pub fn test_boxed_complex_traversal<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let _refs = populate_graph(graph);
let complex_unboxed_result = graph
.walk()
.vertices(VertexSearch::scan())
.edges(EdgeSearch::scan())
.head()
.edges(EdgeSearch::scan())
.head()
.edges(EdgeSearch::scan())
.head()
.edges(EdgeSearch::scan())
.head()
.edges(EdgeSearch::scan())
.head()
.collect::<Vec<_>>();
let complex_boxed_result = graph
.walk()
.vertices(VertexSearch::scan())
.edges(EdgeSearch::scan())
.boxed() .head()
.edges(EdgeSearch::scan())
.head()
.boxed() .edges(EdgeSearch::scan())
.head()
.edges(EdgeSearch::scan())
.boxed() .head()
.edges(EdgeSearch::scan())
.head()
.collect::<Vec<_>>();
assert_eq!(complex_unboxed_result.len(), complex_boxed_result.len());
}
pub fn test_boxed_ultra_long_traversal<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let _refs = populate_graph(graph);
let ultra_long_result = graph
.walk()
.vertices(VertexSearch::scan())
.take(2) .edges(EdgeSearch::scan().outgoing()) .boxed() .head()
.edges(EdgeSearch::scan().outgoing())
.boxed() .head()
.edges(EdgeSearch::scan().outgoing())
.boxed() .head()
.edges(EdgeSearch::scan().outgoing())
.boxed() .head()
.collect::<Vec<_>>();
assert!(ultra_long_result.len() < 1_000_000); }
pub fn test_boxed_mixed_operations<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let _refs = populate_graph(graph);
let mixed_result = graph
.walk()
.vertices(VertexSearch::scan())
.take(2)
.edges(EdgeSearch::scan())
.boxed() .head()
.take(1)
.edges(EdgeSearch::scan())
.boxed() .head()
.collect::<Vec<_>>();
assert!(mixed_result.len() <= 4); }
pub fn test_boxed_edge_walker<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let refs = populate_graph(graph);
let edge_result = graph
.walk()
.vertices_by_id(vec![refs.bryn])
.edges(EdgeSearch::scan().outgoing())
.boxed() .collect::<Vec<_>>();
assert_elements_eq!(
graph,
edge_result,
vec![refs.bryn_knows_julia, refs.bryn_created_graph_api]
);
}
pub fn test_boxed_performance_equivalence<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let _refs = populate_graph(graph);
let unboxed = graph
.walk()
.vertices(VertexSearch::scan())
.edges(EdgeSearch::scan())
.head()
.edges(EdgeSearch::scan())
.head()
.take(2)
.collect::<Vec<_>>();
let boxed = graph
.walk()
.vertices(VertexSearch::scan())
.edges(EdgeSearch::scan())
.boxed() .head()
.edges(EdgeSearch::scan())
.head()
.take(2)
.collect::<Vec<_>>();
assert_eq!(unboxed.len(), boxed.len());
assert!(boxed.len() <= 4); }
pub fn test_boxed_with_context<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let refs = populate_graph(graph);
let result_with_context = graph
.walk()
.vertices_by_id(vec![refs.bryn])
.edges(EdgeSearch::scan().outgoing())
.push_context(|edge, _| format!("edge-{:?}", edge.id()))
.boxed() .head()
.collect::<Vec<_>>();
assert_elements_eq!(graph, result_with_context, vec![refs.graph_api, refs.julia]);
}
#[derive(Clone, Debug, PartialEq)]
struct TestContext {
counter: u32,
label: String,
}
pub fn test_boxed_context_delegation<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let refs = populate_graph(graph);
let result = graph
.walk()
.push_context(TestContext {
counter: 0,
label: "start".to_string(),
})
.vertices_by_id(vec![refs.bryn])
.mutate_context(|_, ctx| {
ctx.counter += 1;
ctx.label = "after_vertex".to_string();
})
.edges(EdgeSearch::scan().outgoing())
.boxed() .mutate_context(|_, ctx| {
ctx.counter += 10; ctx.label = "after_boxing".to_string();
})
.head()
.map(|vertex, context| {
assert_eq!(
context.counter, 11,
"Context counter should be 0 + 1 + 10 = 11"
);
assert_eq!(
context.label, "after_boxing",
"Context label should be updated after boxing"
);
vertex
})
.collect::<Vec<_>>();
assert_eq!(result.len(), 2); }
pub fn test_boxed_context_access_before_next<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let refs = populate_graph(graph);
let result = graph
.walk()
.push_context(TestContext {
counter: 42,
label: "initial".to_string(),
})
.vertices_by_id(vec![refs.bryn])
.edges(EdgeSearch::scan().outgoing())
.boxed() .mutate_context(|_, ctx| {
assert_eq!(ctx.counter, 42, "Initial context should be preserved");
assert_eq!(
ctx.label, "initial",
"Initial context label should be preserved"
);
ctx.counter = 100;
ctx.label = "modified_after_boxing".to_string();
})
.head()
.map(|vertex, context| {
assert_eq!(context.counter, 100, "Context should be modified to 100");
assert_eq!(
context.label, "modified_after_boxing",
"Context label should be updated"
);
vertex
})
.collect::<Vec<_>>();
assert_eq!(result.len(), 2); }
pub fn test_boxed_nested_contexts<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let refs = populate_graph(graph);
let result = graph
.walk()
.push_context("outer")
.vertices_by_id(vec![refs.bryn])
.push_context(|_, parent_ctx| format!("inner-{}", parent_ctx))
.edges(EdgeSearch::scan().outgoing())
.boxed() .head()
.map(|vertex, context| {
assert_eq!(
*context, "inner-outer",
"Nested context should combine properly"
);
assert_eq!(
*context.parent(),
"outer",
"Parent context should be accessible"
);
vertex
})
.collect::<Vec<_>>();
assert_eq!(result.len(), 2); }
pub fn test_boxed_context_persistence<T>(graph: &mut T)
where
T: Graph<Vertex = Vertex, Edge = Edge>,
{
let refs = populate_graph(graph);
let result = graph
.walk()
.push_context(TestContext {
counter: 5,
label: "original".to_string(),
})
.vertices_by_id(vec![refs.bryn, refs.julia])
.boxed() .mutate_context(|_, ctx| {
assert_eq!(ctx.counter, 5, "Counter should start at 5");
assert_eq!(ctx.label, "original", "Label should start as 'original'");
ctx.label = "modified_by_mutate_context".to_string();
ctx.counter = 42;
})
.map(|vertex, context| {
assert_eq!(context.counter, 42, "Counter should be modified to 42");
assert_eq!(
context.label, "modified_by_mutate_context",
"Label should be updated"
);
vertex
})
.collect::<Vec<_>>();
assert_eq!(result.len(), 2); }