use std::sync::Arc;
use selene_core::{GraphId, LabelSet, PropertyValueType, db_string};
use selene_persist::RecoveryProvider;
use super::*;
use crate::core_provider::sections::{decode_graph_types, encode_graph_types};
use crate::graph_types::{
GraphTypeDef, NodeTypeDef, PropertyElementType, PropertyTypeDef, ValidationMode,
};
use crate::{GraphError, SeleneGraph, SharedGraph};
#[test]
fn gtyp_v3_preserves_type_model_fields() {
let graph_type = GraphTypeDef {
name: db_string("core.gtyp.v3").unwrap(),
node_types: vec![NodeTypeDef {
name: db_string("core.gtyp.v3.node").unwrap(),
key_labels: LabelSet::single(db_string("V3Node").unwrap()),
properties: vec![PropertyTypeDef {
name: db_string("core.gtyp.v3.name").unwrap(),
value_type: PropertyValueType::List,
list_element_type: Some(PropertyElementType::List(Box::new(
PropertyElementType::Scalar(PropertyValueType::String),
))),
required: false,
default: None,
immutable: true,
unique: false,
decimal_type: None,
character_string_type: None,
byte_string_type: None,
record_field_types: None,
}],
validation_mode: ValidationMode::Warn,
}],
edge_types: Vec::new(),
};
let graph = SharedGraph::builder(GraphId::new(88))
.bound_to(graph_type.clone())
.unwrap()
.build()
.unwrap()
.read()
.as_ref()
.clone();
let rows = decode_graph_types(&encode_graph_types(&graph).unwrap()).unwrap();
assert_eq!(rows, vec![(0, graph_type)]);
}
#[test]
fn finish_recovery_rejects_gtyp_without_meta() {
let mut graph = SeleneGraph::new(GraphId::new(20));
graph.meta.bound_type = Some(Arc::new(GraphTypeDef {
name: db_string("test.gtyp.no.meta").unwrap(),
node_types: vec![NodeTypeDef {
name: db_string("test.node").unwrap(),
key_labels: LabelSet::single(db_string("Test").unwrap()),
properties: vec![PropertyTypeDef {
name: db_string("name").unwrap(),
value_type: PropertyValueType::String,
list_element_type: None,
required: false,
default: None,
immutable: false,
unique: false,
decimal_type: None,
character_string_type: None,
byte_string_type: None,
record_field_types: None,
}],
validation_mode: crate::ValidationMode::Strict,
}],
edge_types: vec![],
}));
let gtyp_bytes = encode_graph_types(&graph).unwrap();
let provider = CoreProvider::new_for_recovery();
RecoveryProvider::read_section(provider.as_ref(), CORE_GTYP_SUB, >yp_bytes).unwrap();
let err = provider
.finish_recovery(GraphId::new(20), None)
.expect_err("recovery must fail when GTYP is non-empty but META is missing");
assert!(matches!(
err,
GraphError::Provider(ProviderError::Inconsistent { reason })
if reason.contains("GTYP non-empty") && reason.contains("META missing")
));
}