use sqlitegraph::{
EdgeSpec, NeighborQuery, NodeSpec, SnapshotId,
backend::{BackendDirection, GraphBackend, SqliteGraphBackend},
multi_hop::ChainStep,
pattern::PatternQuery,
};
fn make_node_spec(name: &str) -> NodeSpec {
NodeSpec {
kind: "test".to_string(),
name: name.to_string(),
file_path: None,
data: serde_json::json!(null),
}
}
fn insert_edge(backend: &SqliteGraphBackend, from: i64, to: i64) {
backend
.insert_edge(EdgeSpec {
from,
to,
edge_type: "test_edge".to_string(),
data: serde_json::json!(null),
})
.unwrap();
}
fn checkpointed_version(backend: &SqliteGraphBackend) -> u64 {
let n1 = backend.insert_node(make_node_spec("node1")).unwrap();
let n2 = backend.insert_node(make_node_spec("node2")).unwrap();
insert_edge(backend, n1, n2);
let _ = backend.neighbors(
SnapshotId::current(),
n1,
NeighborQuery {
direction: BackendDirection::Outgoing,
edge_type: None,
},
);
backend.graph().checkpoint()
}
#[test]
fn test_sqlite_current_snapshot_works_get_node() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let node_id = backend.insert_node(make_node_spec("test_node")).unwrap();
let node = backend
.get_node(SnapshotId::current(), node_id)
.expect("current snapshot should work");
assert_eq!(node.name, "test_node");
}
#[test]
fn test_sqlite_current_snapshot_works_all_operations() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let n1 = backend.insert_node(make_node_spec("node1")).unwrap();
let n2 = backend.insert_node(make_node_spec("node2")).unwrap();
let n3 = backend.insert_node(make_node_spec("node3")).unwrap();
insert_edge(&backend, n1, n2);
insert_edge(&backend, n2, n3);
let current = SnapshotId::current();
assert!(backend.get_node(current, n1).is_ok());
assert!(
backend
.neighbors(
current,
n1,
NeighborQuery {
direction: BackendDirection::Outgoing,
edge_type: None,
}
)
.is_ok()
);
assert!(backend.bfs(current, n1, 2).is_ok());
assert!(backend.shortest_path(current, n1, n3).is_ok());
assert!(backend.node_degree(current, n1).is_ok());
assert!(
backend
.k_hop(current, n1, 2, BackendDirection::Outgoing)
.is_ok()
);
assert!(
backend
.k_hop_filtered(current, n1, 2, BackendDirection::Outgoing, &["test_edge"])
.is_ok()
);
assert!(
backend
.chain_query(
current,
n1,
&[ChainStep {
direction: BackendDirection::Outgoing,
edge_type: None,
}]
)
.is_ok()
);
assert!(
backend
.pattern_search(current, n1, &PatternQuery::default())
.is_ok()
);
assert!(backend.query_nodes_by_kind(current, "test").is_ok());
assert!(
backend
.query_nodes_by_name_pattern(current, "node*")
.is_ok()
);
}
#[test]
fn test_sqlite_historical_snapshot_neighbors_succeeds() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let node1 = 1; let neighbors = backend
.neighbors(
SnapshotId::from_lsn(v),
node1,
NeighborQuery {
direction: BackendDirection::Outgoing,
edge_type: None,
},
)
.expect("checkpointed historical neighbors should succeed");
assert_eq!(neighbors, vec![2]);
}
#[test]
fn test_sqlite_historical_snapshot_bfs_succeeds() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let bfs = backend
.bfs(SnapshotId::from_lsn(v), 1, 5)
.expect("checkpointed historical bfs should succeed");
assert_eq!(bfs, vec![1, 2]);
}
#[test]
fn test_sqlite_uncheckpointed_version_errors_neighbors() {
let backend = SqliteGraphBackend::in_memory().unwrap();
backend.insert_node(make_node_spec("node1")).unwrap();
let result = backend.neighbors(
SnapshotId::from_lsn(999),
1,
NeighborQuery {
direction: BackendDirection::Outgoing,
edge_type: None,
},
);
assert!(result.is_err(), "uncheckpointed version should error");
assert!(
result.unwrap_err().to_string().contains("not available"),
"error should mention the version is not available"
);
}
#[test]
fn test_sqlite_uncheckpointed_version_errors_bfs() {
let backend = SqliteGraphBackend::in_memory().unwrap();
backend.insert_node(make_node_spec("node1")).unwrap();
let result = backend.bfs(SnapshotId::from_lsn(555), 1, 2);
assert!(result.is_err(), "uncheckpointed version should error");
}
#[test]
fn test_sqlite_historical_snapshot_rejected_get_node() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let result = backend.get_node(SnapshotId::from_lsn(v), 1);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("not supported for")
);
}
#[test]
fn test_sqlite_historical_snapshot_rejected_shortest_path() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let result = backend.shortest_path(SnapshotId::from_lsn(v), 1, 2);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("not supported for")
);
}
#[test]
fn test_sqlite_historical_snapshot_rejected_node_degree() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let result = backend.node_degree(SnapshotId::from_lsn(v), 1);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("not supported for")
);
}
#[test]
fn test_sqlite_historical_snapshot_rejected_k_hop() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let result = backend.k_hop(SnapshotId::from_lsn(v), 1, 2, BackendDirection::Outgoing);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("not supported for")
);
}
#[test]
fn test_sqlite_historical_snapshot_rejected_k_hop_filtered() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let result = backend.k_hop_filtered(
SnapshotId::from_lsn(v),
1,
2,
BackendDirection::Outgoing,
&["x"],
);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("not supported for")
);
}
#[test]
fn test_sqlite_historical_snapshot_rejected_chain_query() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let result = backend.chain_query(
SnapshotId::from_lsn(v),
1,
&[ChainStep {
direction: BackendDirection::Outgoing,
edge_type: None,
}],
);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("not supported for")
);
}
#[test]
fn test_sqlite_historical_snapshot_rejected_pattern_search() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let result = backend.pattern_search(SnapshotId::from_lsn(v), 1, &PatternQuery::default());
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("not supported for")
);
}
#[test]
fn test_sqlite_historical_snapshot_rejected_query_nodes_by_kind() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let result = backend.query_nodes_by_kind(SnapshotId::from_lsn(v), "test");
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("not supported for")
);
}
#[test]
fn test_sqlite_historical_snapshot_rejected_query_nodes_by_name_pattern() {
let backend = SqliteGraphBackend::in_memory().unwrap();
let v = checkpointed_version(&backend);
let result = backend.query_nodes_by_name_pattern(SnapshotId::from_lsn(v), "node*");
assert!(result.is_err());
assert!(
result
.unwrap_err()
.to_string()
.contains("not supported for")
);
}