#![cfg(feature = "graph")]
use vyre_primitives::graph::csr_forward_traverse::*;
use vyre_primitives::graph::program_graph::*;
#[test]
fn validate_program_graph_empty() {
let shape = ProgramGraphShape::new(0, 0);
let result = validate_program_graph(shape, &[], &[0], &[0], &[0], &[]);
assert!(
result.is_ok(),
"empty graph with placeholder edges should validate"
);
}
#[test]
fn validate_program_graph_mismatched_nodes_len() {
let shape = ProgramGraphShape::new(3, 2);
let err = validate_program_graph(shape, &[0, 0], &[0, 1, 2, 2], &[1, 2], &[1, 1], &[0, 0, 0])
.unwrap_err();
assert!(matches!(err, GraphValidationError::NodesLen { .. }));
}
#[test]
fn validate_program_graph_non_monotonic_offsets() {
let shape = ProgramGraphShape::new(2, 1);
let err = validate_program_graph(shape, &[0, 0], &[0, 2, 1], &[0], &[0], &[0, 0]).unwrap_err();
assert!(matches!(
err,
GraphValidationError::NonMonotonicOffsets { .. }
));
}
#[test]
fn validate_program_graph_oob_edge_target() {
let shape = ProgramGraphShape::new(2, 1);
let err = validate_program_graph(shape, &[0, 0], &[0, 1, 1], &[5], &[0], &[0, 0]).unwrap_err();
assert!(matches!(
err,
GraphValidationError::EdgeOutOfRange { target: 5, .. }
));
}
#[test]
fn validate_program_graph_first_offset_nonzero() {
let shape = ProgramGraphShape::new(2, 1);
let err = validate_program_graph(shape, &[0, 0], &[1, 1, 1], &[0], &[0], &[0, 0]).unwrap_err();
assert!(matches!(
err,
GraphValidationError::NonMonotonicOffsets { index: 0 }
));
}
#[test]
fn validate_program_graph_u32_max_node_count() {
let shape = ProgramGraphShape::new(u32::MAX, 0);
let nodes: &[u32] = &[];
let edge_offsets = &[0u32];
let err = validate_program_graph(shape, nodes, edge_offsets, &[0], &[0], nodes).unwrap_err();
assert!(
matches!(
err,
GraphValidationError::NodesLen { .. } | GraphValidationError::EdgeOffsetsLen { .. }
),
"got unexpected error variant: {err:?}"
);
}
#[test]
fn csr_forward_traverse_empty_frontier() {
let got = cpu_ref(
4,
&[0, 2, 3, 4, 4],
&[1, 2, 3, 3],
&[1, 1, 1, 1],
&[0],
0xFFFF_FFFF,
);
assert_eq!(got, vec![0]);
}
#[test]
fn csr_forward_traverse_zero_nodes() {
let got = cpu_ref(0, &[0], &[], &[], &[], 0xFFFF_FFFF);
assert_eq!(got, vec![]);
}
#[test]
fn csr_forward_traverse_malformed_csr_panics() {
let result = std::panic::catch_unwind(|| cpu_ref(2, &[0], &[1], &[1], &[0b11], 0xFFFF_FFFF));
assert!(result.is_err(), "missing edge_offsets entry must panic");
}
#[test]
fn csr_forward_traverse_edge_mask_filters() {
let got = cpu_ref(
4,
&[0, 2, 3, 4, 4],
&[1, 2, 3, 3],
&[0b10, 0b01, 0b01, 0b01],
&[0b0001],
0b01,
);
assert_eq!(got, vec![0b0100]);
}
#[test]
fn csr_forward_traverse_oob_target_silently_dropped() {
let got = cpu_ref(2, &[0, 2, 2], &[1, 100], &[1, 1], &[0b0001], 0xFFFF_FFFF);
assert_eq!(got, vec![0b0010]);
}