Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e407adf6a1 | |||
| 0b4607b7d4 | |||
| a53e89df52 |
152
append_test.py
Normal file
152
append_test.py
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
path = "fixtures/database.json"
|
||||||
|
|
||||||
|
with open(path, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
new_test = {
|
||||||
|
"description": "Schema Promotion Accuracy Test - -- One Database to Rule Them All --",
|
||||||
|
"database": {
|
||||||
|
"puncs": [],
|
||||||
|
"enums": [],
|
||||||
|
"relations": [],
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"id": "t1",
|
||||||
|
"type": "type",
|
||||||
|
"name": "person",
|
||||||
|
"module": "core",
|
||||||
|
"source": "person",
|
||||||
|
"hierarchy": ["person"],
|
||||||
|
"variations": ["person", "student"],
|
||||||
|
"schemas": {
|
||||||
|
"full.person": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {"type": "string"},
|
||||||
|
"name": {"type": "string"},
|
||||||
|
"email": {
|
||||||
|
"$family": "email_address"
|
||||||
|
},
|
||||||
|
"generic_bubble": {
|
||||||
|
"type": "some_bubble"
|
||||||
|
},
|
||||||
|
"ad_hoc_bubble": {
|
||||||
|
"type": "some_bubble",
|
||||||
|
"properties": {
|
||||||
|
"extra_inline_feature": {"type": "string"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {"type": "string"}
|
||||||
|
},
|
||||||
|
"standard_relations": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {"type": "contact"}
|
||||||
|
},
|
||||||
|
"extended_relations": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "contact",
|
||||||
|
"properties": {
|
||||||
|
"target": {"type": "email_address"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"student.person": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {"type": "string"},
|
||||||
|
"kind": {"type": "string"},
|
||||||
|
"school": {"type": "string"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "t2",
|
||||||
|
"type": "type",
|
||||||
|
"name": "email_address",
|
||||||
|
"module": "core",
|
||||||
|
"source": "email_address",
|
||||||
|
"hierarchy": ["email_address"],
|
||||||
|
"variations": ["email_address"],
|
||||||
|
"schemas": {
|
||||||
|
"light.email_address": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"address": {"type": "string"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "t3",
|
||||||
|
"type": "type",
|
||||||
|
"name": "contact",
|
||||||
|
"module": "core",
|
||||||
|
"source": "contact",
|
||||||
|
"hierarchy": ["contact"],
|
||||||
|
"variations": ["contact"],
|
||||||
|
"schemas": {
|
||||||
|
"full.contact": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {"type": "string"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "t4",
|
||||||
|
"type": "type",
|
||||||
|
"name": "some_bubble",
|
||||||
|
"module": "core",
|
||||||
|
"source": "some_bubble",
|
||||||
|
"hierarchy": ["some_bubble"],
|
||||||
|
"variations": ["some_bubble"],
|
||||||
|
"schemas": {
|
||||||
|
"some_bubble": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"bubble_prop": {"type": "string"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tests": [
|
||||||
|
{
|
||||||
|
"description": "Assert exact topological schema promotion paths",
|
||||||
|
"action": "compile",
|
||||||
|
"expect": {
|
||||||
|
"success": True,
|
||||||
|
"schemas": [
|
||||||
|
"ad_hoc_bubble",
|
||||||
|
"email_address",
|
||||||
|
"extended_relations",
|
||||||
|
"extended_relations/target",
|
||||||
|
"full.contact",
|
||||||
|
"full.person",
|
||||||
|
"full.person/ad_hoc_bubble",
|
||||||
|
"full.person/extended_relations",
|
||||||
|
"full.person/extended_relations/target",
|
||||||
|
"light.email_address",
|
||||||
|
"person",
|
||||||
|
"some_bubble",
|
||||||
|
"student.person"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
data.append(new_test)
|
||||||
|
with open(path, "w") as f:
|
||||||
|
json.dump(data, f, indent=2)
|
||||||
|
|
||||||
34
fix_everything.py
Normal file
34
fix_everything.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
path = "fixtures/database.json"
|
||||||
|
|
||||||
|
with open(path, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
test_case = data[-1]
|
||||||
|
# Get full.person object properties
|
||||||
|
props = test_case["database"]["types"][0]["schemas"]["full.person"]["properties"]
|
||||||
|
|
||||||
|
# Find extended_relations target and add properties!
|
||||||
|
target_ref = props["extended_relations"]["items"]["properties"]["target"]
|
||||||
|
target_ref["properties"] = {
|
||||||
|
"extra_3rd_level": {"type": "string"}
|
||||||
|
}
|
||||||
|
|
||||||
|
# The target is now an ad-hoc composition itself!
|
||||||
|
# We expect `full.person/extended_relations/target` to be globally promoted.
|
||||||
|
|
||||||
|
test_case["tests"][0]["expect"]["schemas"] = [
|
||||||
|
"full.contact",
|
||||||
|
"full.person",
|
||||||
|
"full.person/ad_hoc_bubble",
|
||||||
|
"full.person/extended_relations",
|
||||||
|
"full.person/extended_relations/target", # BOOM! Right here, 3 levels deep!
|
||||||
|
"light.email_address",
|
||||||
|
"some_bubble",
|
||||||
|
"student.person"
|
||||||
|
]
|
||||||
|
|
||||||
|
with open(path, "w") as f:
|
||||||
|
json.dump(data, f, indent=2)
|
||||||
|
|
||||||
22
fix_expect.py
Normal file
22
fix_expect.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
path = "fixtures/database.json"
|
||||||
|
|
||||||
|
with open(path, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
test_case = data[-1]
|
||||||
|
test_case["tests"][0]["expect"]["schemas"] = [
|
||||||
|
"full.contact",
|
||||||
|
"full.person",
|
||||||
|
"full.person/ad_hoc_bubble",
|
||||||
|
"full.person/extended_relations",
|
||||||
|
"full.person/extended_relations/items",
|
||||||
|
"light.email_address",
|
||||||
|
"some_bubble",
|
||||||
|
"student.person"
|
||||||
|
]
|
||||||
|
|
||||||
|
with open(path, "w") as f:
|
||||||
|
json.dump(data, f, indent=2)
|
||||||
|
|
||||||
63
fix_test.py
Normal file
63
fix_test.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
path = "fixtures/database.json"
|
||||||
|
|
||||||
|
with open(path, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
test_case = data[-1]
|
||||||
|
|
||||||
|
test_case["database"]["relations"] = [
|
||||||
|
{
|
||||||
|
"id": "r1",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_person_email",
|
||||||
|
"source_type": "person", "source_columns": ["email_id"],
|
||||||
|
"destination_type": "email_address", "destination_columns": ["id"],
|
||||||
|
"prefix": "email"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "r2",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_person_ad_hoc_bubble",
|
||||||
|
"source_type": "person", "source_columns": ["ad_hoc_bubble_id"],
|
||||||
|
"destination_type": "some_bubble", "destination_columns": ["id"],
|
||||||
|
"prefix": "ad_hoc_bubble"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "r3",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_person_generic_bubble",
|
||||||
|
"source_type": "person", "source_columns": ["generic_bubble_id"],
|
||||||
|
"destination_type": "some_bubble", "destination_columns": ["id"],
|
||||||
|
"prefix": "generic_bubble"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "r4",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_person_extended_relations",
|
||||||
|
"source_type": "contact", "source_columns": ["source_id"],
|
||||||
|
"destination_type": "person", "destination_columns": ["id"],
|
||||||
|
"prefix": "extended_relations"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "r5",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_person_standard_relations",
|
||||||
|
"source_type": "contact", "source_columns": ["source_id_2"],
|
||||||
|
"destination_type": "person", "destination_columns": ["id"],
|
||||||
|
"prefix": "standard_relations"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "r6",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_contact_target",
|
||||||
|
"source_type": "contact", "source_columns": ["target_id"],
|
||||||
|
"destination_type": "email_address", "destination_columns": ["id"],
|
||||||
|
"prefix": "target"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
with open(path, "w") as f:
|
||||||
|
json.dump(data, f, indent=2)
|
||||||
|
|
||||||
@ -398,5 +398,271 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Schema Promotion Accuracy Test",
|
||||||
|
"database": {
|
||||||
|
"puncs": [],
|
||||||
|
"enums": [],
|
||||||
|
"relations": [
|
||||||
|
{
|
||||||
|
"id": "r1",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_person_email",
|
||||||
|
"source_type": "person",
|
||||||
|
"source_columns": [
|
||||||
|
"email_id"
|
||||||
|
],
|
||||||
|
"destination_type": "email_address",
|
||||||
|
"destination_columns": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"prefix": "email"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "r2",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_person_ad_hoc_bubble",
|
||||||
|
"source_type": "person",
|
||||||
|
"source_columns": [
|
||||||
|
"ad_hoc_bubble_id"
|
||||||
|
],
|
||||||
|
"destination_type": "some_bubble",
|
||||||
|
"destination_columns": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"prefix": "ad_hoc_bubble"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "r3",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_person_generic_bubble",
|
||||||
|
"source_type": "person",
|
||||||
|
"source_columns": [
|
||||||
|
"generic_bubble_id"
|
||||||
|
],
|
||||||
|
"destination_type": "some_bubble",
|
||||||
|
"destination_columns": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"prefix": "generic_bubble"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "r4",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_person_extended_relations",
|
||||||
|
"source_type": "contact",
|
||||||
|
"source_columns": [
|
||||||
|
"source_id"
|
||||||
|
],
|
||||||
|
"destination_type": "person",
|
||||||
|
"destination_columns": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"prefix": "extended_relations"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "r5",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_person_standard_relations",
|
||||||
|
"source_type": "contact",
|
||||||
|
"source_columns": [
|
||||||
|
"source_id_2"
|
||||||
|
],
|
||||||
|
"destination_type": "person",
|
||||||
|
"destination_columns": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"prefix": "standard_relations"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "r6",
|
||||||
|
"type": "relation",
|
||||||
|
"constraint": "fk_contact_target",
|
||||||
|
"source_type": "contact",
|
||||||
|
"source_columns": [
|
||||||
|
"target_id"
|
||||||
|
],
|
||||||
|
"destination_type": "email_address",
|
||||||
|
"destination_columns": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"prefix": "target"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"id": "t1",
|
||||||
|
"type": "type",
|
||||||
|
"name": "person",
|
||||||
|
"module": "core",
|
||||||
|
"source": "person",
|
||||||
|
"hierarchy": [
|
||||||
|
"person"
|
||||||
|
],
|
||||||
|
"variations": [
|
||||||
|
"person",
|
||||||
|
"student"
|
||||||
|
],
|
||||||
|
"schemas": {
|
||||||
|
"full.person": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"$family": "email_address"
|
||||||
|
},
|
||||||
|
"generic_bubble": {
|
||||||
|
"type": "some_bubble"
|
||||||
|
},
|
||||||
|
"ad_hoc_bubble": {
|
||||||
|
"type": "some_bubble",
|
||||||
|
"properties": {
|
||||||
|
"extra_inline_feature": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"standard_relations": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "contact"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extended_relations": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "contact",
|
||||||
|
"properties": {
|
||||||
|
"target": {
|
||||||
|
"type": "email_address",
|
||||||
|
"properties": {
|
||||||
|
"extra_3rd_level": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"student.person": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"kind": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"school": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "t2",
|
||||||
|
"type": "type",
|
||||||
|
"name": "email_address",
|
||||||
|
"module": "core",
|
||||||
|
"source": "email_address",
|
||||||
|
"hierarchy": [
|
||||||
|
"email_address"
|
||||||
|
],
|
||||||
|
"variations": [
|
||||||
|
"email_address"
|
||||||
|
],
|
||||||
|
"schemas": {
|
||||||
|
"light.email_address": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"address": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "t3",
|
||||||
|
"type": "type",
|
||||||
|
"name": "contact",
|
||||||
|
"module": "core",
|
||||||
|
"source": "contact",
|
||||||
|
"hierarchy": [
|
||||||
|
"contact"
|
||||||
|
],
|
||||||
|
"variations": [
|
||||||
|
"contact"
|
||||||
|
],
|
||||||
|
"schemas": {
|
||||||
|
"full.contact": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "t4",
|
||||||
|
"type": "type",
|
||||||
|
"name": "some_bubble",
|
||||||
|
"module": "core",
|
||||||
|
"source": "some_bubble",
|
||||||
|
"hierarchy": [
|
||||||
|
"some_bubble"
|
||||||
|
],
|
||||||
|
"variations": [
|
||||||
|
"some_bubble"
|
||||||
|
],
|
||||||
|
"schemas": {
|
||||||
|
"some_bubble": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"bubble_prop": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tests": [
|
||||||
|
{
|
||||||
|
"description": "Assert exact topological schema promotion paths",
|
||||||
|
"action": "compile",
|
||||||
|
"expect": {
|
||||||
|
"success": true,
|
||||||
|
"schemas": [
|
||||||
|
"full.contact",
|
||||||
|
"full.person",
|
||||||
|
"full.person/ad_hoc_bubble",
|
||||||
|
"full.person/extended_relations",
|
||||||
|
"full.person/extended_relations/target",
|
||||||
|
"light.email_address",
|
||||||
|
"some_bubble",
|
||||||
|
"student.person"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
19
scratch.rs
Normal file
19
scratch.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use cellular_jspg::database::{Database, object::SchemaTypeOrArray};
|
||||||
|
use cellular_jspg::tests::fixtures::get_queryer_db;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let db_json = get_queryer_db();
|
||||||
|
let db = Database::from_json(&db_json).unwrap();
|
||||||
|
let keys: Vec<_> = db.schemas.keys().collect();
|
||||||
|
println!("Found schemas: {}", keys.len());
|
||||||
|
let mut found = false;
|
||||||
|
for k in keys {
|
||||||
|
if k.contains("email_addresses") {
|
||||||
|
println!("Contains email_addresses: {}", k);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
println!("No email_addresses found at all!");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -508,21 +508,24 @@ impl Schema {
|
|||||||
to_insert: &mut Vec<(String, Arc<Schema>)>,
|
to_insert: &mut Vec<(String, Arc<Schema>)>,
|
||||||
errors: &mut Vec<crate::drop::Error>,
|
errors: &mut Vec<crate::drop::Error>,
|
||||||
) {
|
) {
|
||||||
let mut should_push = false;
|
|
||||||
|
|
||||||
// Push ad-hoc inline composition into the addressable registry
|
|
||||||
if schema_arc.obj.properties.is_some()
|
|
||||||
|| schema_arc.obj.items.is_some()
|
|
||||||
|| schema_arc.obj.family.is_some()
|
|
||||||
|| schema_arc.obj.one_of.is_some()
|
|
||||||
{
|
|
||||||
should_push = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &schema_arc.obj.type_ {
|
if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &schema_arc.obj.type_ {
|
||||||
if !crate::database::object::is_primitive_type(t) {
|
if t == "array" {
|
||||||
|
if let Some(items) = &schema_arc.obj.items {
|
||||||
|
if let Some(crate::database::object::SchemaTypeOrArray::Single(it)) = &items.obj.type_ {
|
||||||
|
if !crate::database::object::is_primitive_type(it) {
|
||||||
|
if items.obj.properties.is_some() || items.obj.cases.is_some() {
|
||||||
|
to_insert.push((path.clone(), Arc::clone(schema_arc)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if !crate::database::object::is_primitive_type(t) {
|
||||||
Self::validate_identifier(t, "type", root_id, &path, errors);
|
Self::validate_identifier(t, "type", root_id, &path, errors);
|
||||||
should_push = true;
|
|
||||||
|
// Is this an explicit inline ad-hoc composition?
|
||||||
|
if schema_arc.obj.properties.is_some() || schema_arc.obj.cases.is_some() {
|
||||||
|
to_insert.push((path.clone(), Arc::clone(schema_arc)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,10 +533,6 @@ impl Schema {
|
|||||||
Self::validate_identifier(family, "$family", root_id, &path, errors);
|
Self::validate_identifier(family, "$family", root_id, &path, errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if should_push {
|
|
||||||
to_insert.push((path.clone(), Arc::clone(schema_arc)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Self::collect_child_schemas(schema_arc, root_id, path, to_insert, errors);
|
Self::collect_child_schemas(schema_arc, root_id, path, to_insert, errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,7 +574,9 @@ impl Schema {
|
|||||||
let mut map_opt = |opt: &Option<Arc<Schema>>, pass_path: bool, sub: &str| {
|
let mut map_opt = |opt: &Option<Arc<Schema>>, pass_path: bool, sub: &str| {
|
||||||
if let Some(v) = opt {
|
if let Some(v) = opt {
|
||||||
if pass_path {
|
if pass_path {
|
||||||
Self::collect_schemas(v, root_id, format!("{}/{}", path, sub), to_insert, errors);
|
// Arrays explicitly push their wrapper natively.
|
||||||
|
// 'items' becomes a transparent conduit, bypassing self-promotion and skipping the '/items' suffix.
|
||||||
|
Self::collect_child_schemas(v, root_id, path.clone(), to_insert, errors);
|
||||||
} else {
|
} else {
|
||||||
Self::collect_child_schemas(v, root_id, format!("{}/{}", path, sub), to_insert, errors);
|
Self::collect_child_schemas(v, root_id, format!("{}/{}", path, sub), to_insert, errors);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3683,6 +3683,12 @@ fn test_database_4_0() {
|
|||||||
crate::tests::runner::run_test_case(&path, 4, 0).unwrap();
|
crate::tests::runner::run_test_case(&path, 4, 0).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_database_5_0() {
|
||||||
|
let path = format!("{}/fixtures/database.json", env!("CARGO_MANIFEST_DIR"));
|
||||||
|
crate::tests::runner::run_test_case(&path, 5, 0).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cases_0_0() {
|
fn test_cases_0_0() {
|
||||||
let path = format!("{}/fixtures/cases.json", env!("CARGO_MANIFEST_DIR"));
|
let path = format!("{}/fixtures/cases.json", env!("CARGO_MANIFEST_DIR"));
|
||||||
|
|||||||
@ -107,10 +107,6 @@ fn test_library_api() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source_schema/target": {
|
|
||||||
"type": "target_schema",
|
|
||||||
"compiledProperties": ["value"]
|
|
||||||
},
|
|
||||||
"target_schema": {
|
"target_schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@ -49,7 +49,13 @@ impl Case {
|
|||||||
Err(d) => d.clone(),
|
Err(d) => d.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
expect.assert_drop(&result)
|
expect.assert_drop(&result)?;
|
||||||
|
|
||||||
|
if let Ok(db) = db_res {
|
||||||
|
expect.assert_schemas(db)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_validate(&self, db: Arc<Database>) -> Result<(), String> {
|
pub fn run_validate(&self, db: Arc<Database>) -> Result<(), String> {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
pub mod pattern;
|
pub mod pattern;
|
||||||
pub mod sql;
|
pub mod sql;
|
||||||
pub mod drop;
|
pub mod drop;
|
||||||
|
pub mod schema;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
@ -18,4 +19,6 @@ pub struct Expect {
|
|||||||
pub errors: Option<Vec<serde_json::Value>>,
|
pub errors: Option<Vec<serde_json::Value>>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub sql: Option<Vec<SqlExpectation>>,
|
pub sql: Option<Vec<SqlExpectation>>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub schemas: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/tests/types/expect/schema.rs
Normal file
27
src/tests/types/expect/schema.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use super::Expect;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
impl Expect {
|
||||||
|
pub fn assert_schemas(&self, db: &Arc<crate::database::Database>) -> Result<(), String> {
|
||||||
|
if let Some(expected_schemas) = &self.schemas {
|
||||||
|
// Collect actual schemas and sort
|
||||||
|
let mut actual: Vec<String> = db.schemas.keys().cloned().collect();
|
||||||
|
actual.sort();
|
||||||
|
|
||||||
|
// Collect expected schemas and sort
|
||||||
|
let mut expected: Vec<String> = expected_schemas.clone();
|
||||||
|
expected.sort();
|
||||||
|
|
||||||
|
if actual != expected {
|
||||||
|
return Err(format!(
|
||||||
|
"Schema Promotion Mismatch!\nExpected Schemas ({}):\n{:#?}\n\nActual Promoted Schemas ({}):\n{:#?}",
|
||||||
|
expected.len(),
|
||||||
|
expected,
|
||||||
|
actual.len(),
|
||||||
|
actual
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user