use datafold::schema::types::{
DeclarativeSchemaDefinition, JsonTopology, PrimitiveType, SchemaType, TopologyNode,
};
use std::collections::HashMap;
#[test]
fn test_field_topology_hash_is_computed() {
let mut schema = DeclarativeSchemaDefinition::new(
"TestSchema".to_string(),
SchemaType::Single,
None,
Some(vec!["name".to_string()]),
None,
None,
);
schema.set_field_topology(
"name".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
}),
);
assert!(schema.field_topology_hashes.is_some());
let hashes = schema.field_topology_hashes.as_ref().unwrap();
assert!(hashes.contains_key("name"));
let hash = hashes.get("name").unwrap();
assert!(!hash.is_empty());
assert_eq!(hash.len(), 64); }
#[test]
fn test_schema_topology_hash_is_computed() {
let mut schema = DeclarativeSchemaDefinition::new(
"TestSchema".to_string(),
SchemaType::Single,
None,
Some(vec!["name".to_string(), "age".to_string()]),
None,
None,
);
schema.set_field_topology(
"name".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
}),
);
schema.set_field_topology(
"age".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::Number,
classifications: None,
}),
);
assert!(schema.topology_hash.is_some());
let hash = schema.topology_hash.as_ref().unwrap();
assert!(!hash.is_empty());
assert_eq!(hash.len(), 64); }
#[test]
fn test_same_topologies_produce_same_hash() {
let mut schema1 = DeclarativeSchemaDefinition::new(
"Schema1".to_string(),
SchemaType::Single,
None,
Some(vec!["name".to_string(), "age".to_string()]),
None,
None,
);
let mut schema2 = DeclarativeSchemaDefinition::new(
"Schema2".to_string(),
SchemaType::Single,
None,
Some(vec!["name".to_string(), "age".to_string()]),
None,
None,
);
schema1.set_field_topology(
"name".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
}),
);
schema1.set_field_topology(
"age".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::Number,
classifications: None,
}),
);
schema2.set_field_topology(
"name".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
}),
);
schema2.set_field_topology(
"age".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::Number,
classifications: None,
}),
);
assert_eq!(schema1.topology_hash, schema2.topology_hash);
assert_eq!(
schema1.get_field_topology_hash("name"),
schema2.get_field_topology_hash("name")
);
assert_eq!(
schema1.get_field_topology_hash("age"),
schema2.get_field_topology_hash("age")
);
}
#[test]
fn test_different_topologies_produce_different_hash() {
let mut schema1 = DeclarativeSchemaDefinition::new(
"Schema1".to_string(),
SchemaType::Single,
None,
Some(vec!["data".to_string()]),
None,
None,
);
let mut schema2 = DeclarativeSchemaDefinition::new(
"Schema2".to_string(),
SchemaType::Single,
None,
Some(vec!["data".to_string()]),
None,
None,
);
schema1.set_field_topology(
"data".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
}),
);
schema2.set_field_topology(
"data".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::Number,
classifications: None,
}),
);
assert_ne!(schema1.topology_hash, schema2.topology_hash);
assert_ne!(
schema1.get_field_topology_hash("data"),
schema2.get_field_topology_hash("data")
);
}
#[test]
fn test_field_order_independent_schema_hash() {
let mut schema1 = DeclarativeSchemaDefinition::new(
"Schema1".to_string(),
SchemaType::Single,
None,
Some(vec!["name".to_string(), "age".to_string()]),
None,
None,
);
let mut schema2 = DeclarativeSchemaDefinition::new(
"Schema2".to_string(),
SchemaType::Single,
None,
Some(vec!["age".to_string(), "name".to_string()]), None,
None,
);
schema1.set_field_topology(
"name".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
}),
);
schema1.set_field_topology(
"age".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::Number,
classifications: None,
}),
);
schema2.set_field_topology(
"age".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::Number,
classifications: None,
}),
);
schema2.set_field_topology(
"name".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
}),
);
assert_eq!(schema1.topology_hash, schema2.topology_hash);
}
#[test]
fn test_nested_topology_hash() {
let mut schema = DeclarativeSchemaDefinition::new(
"TestSchema".to_string(),
SchemaType::Single,
None,
Some(vec!["user".to_string()]),
None,
None,
);
let mut user_fields = HashMap::new();
user_fields.insert(
"id".to_string(),
TopologyNode::Primitive {
value: PrimitiveType::Number,
classifications: None,
},
);
user_fields.insert(
"name".to_string(),
TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
},
);
schema.set_field_topology(
"user".to_string(),
JsonTopology::new(TopologyNode::Object { value: user_fields }),
);
assert!(schema.get_field_topology_hash("user").is_some());
assert!(schema.get_topology_hash().is_some());
}
#[test]
fn test_array_topology_hash() {
let mut schema = DeclarativeSchemaDefinition::new(
"TestSchema".to_string(),
SchemaType::Single,
None,
Some(vec!["tags".to_string()]),
None,
None,
);
schema.set_field_topology(
"tags".to_string(),
JsonTopology::new(TopologyNode::Array {
value: Box::new(TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
}),
}),
);
assert!(schema.get_field_topology_hash("tags").is_some());
assert!(schema.get_topology_hash().is_some());
}
#[test]
fn test_topology_hash_persists_through_serialization() {
let mut schema = DeclarativeSchemaDefinition::new(
"TestSchema".to_string(),
SchemaType::Single,
None,
Some(vec!["name".to_string(), "age".to_string()]),
None,
None,
);
schema.set_field_topology(
"name".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
}),
);
schema.set_field_topology(
"age".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::Number,
classifications: None,
}),
);
let original_hash = schema.topology_hash.clone();
let original_field_hashes = schema.field_topology_hashes.clone();
let serialized = serde_json::to_string(&schema).expect("Failed to serialize");
let deserialized: DeclarativeSchemaDefinition =
serde_json::from_str(&serialized).expect("Failed to deserialize");
assert_eq!(deserialized.topology_hash, original_hash);
assert_eq!(deserialized.field_topology_hashes, original_field_hashes);
}
#[test]
fn test_topology_hash_changes_when_topology_changes() {
let mut schema = DeclarativeSchemaDefinition::new(
"TestSchema".to_string(),
SchemaType::Single,
None,
Some(vec!["data".to_string()]),
None,
None,
);
schema.set_field_topology(
"data".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::String,
classifications: None,
}),
);
let initial_hash = schema.topology_hash.clone();
let initial_field_hash = schema.get_field_topology_hash("data").cloned();
schema.set_field_topology(
"data".to_string(),
JsonTopology::new(TopologyNode::Primitive {
value: PrimitiveType::Number,
classifications: None,
}),
);
let new_hash = schema.topology_hash.clone();
let new_field_hash = schema.get_field_topology_hash("data").cloned();
assert_ne!(initial_hash, new_hash);
assert_ne!(initial_field_hash, new_field_hash);
}