1pub const ORM_IR_JSON_SCHEMA: &str = include_str!("../schemas/radixdb.orm.v1.schema.json");
4pub const SCHEMA_DESCRIPTOR_JSON_SCHEMA: &str =
5 include_str!("../schemas/radixdb.schema.v1.schema.json");
6pub const GUI_TABLE_FORM_JSON_SCHEMA: &str =
7 include_str!("../schemas/radixdb.gui.table-form.v1.schema.json");
8pub const ORM_CONFORMANCE_MANIFEST: &str =
9 include_str!("../schemas/radixdb.orm.v1.conformance.json");
10pub const ORM_CONFORMANCE_FIXTURES: &str = include_str!("../schemas/radixdb.orm.v1.fixtures.json");
11
12#[cfg(test)]
13mod tests {
14 use std::collections::BTreeSet;
15
16 use super::*;
17
18 #[test]
19 fn published_artifacts_are_json_and_language_neutral() {
20 for artifact in [
21 ORM_IR_JSON_SCHEMA,
22 SCHEMA_DESCRIPTOR_JSON_SCHEMA,
23 GUI_TABLE_FORM_JSON_SCHEMA,
24 ORM_CONFORMANCE_MANIFEST,
25 ORM_CONFORMANCE_FIXTURES,
26 ] {
27 serde_json::from_str::<serde_json::Value>(artifact).unwrap();
28 assert!(!artifact.contains("std::"));
29 assert!(!artifact.contains("radixdb_orm::"));
30 }
31 }
32
33 #[test]
34 fn published_json_schemas_are_valid_and_accept_every_ir_fixture() {
35 for artifact in [
36 ORM_IR_JSON_SCHEMA,
37 SCHEMA_DESCRIPTOR_JSON_SCHEMA,
38 GUI_TABLE_FORM_JSON_SCHEMA,
39 ] {
40 let schema: serde_json::Value = serde_json::from_str(artifact).unwrap();
41 if let Err(error) = jsonschema::meta::validate(&schema) {
42 panic!("invalid published JSON Schema: {error}");
43 }
44 }
45
46 let schema: serde_json::Value = serde_json::from_str(ORM_IR_JSON_SCHEMA).unwrap();
47 let validator = jsonschema::validator_for(&schema).unwrap();
48 let fixtures: serde_json::Value = serde_json::from_str(ORM_CONFORMANCE_FIXTURES).unwrap();
49 for case in fixtures["cases"].as_array().expect("fixture cases") {
50 let id = case["id"].as_str().expect("fixture id");
51 for (index, step) in case["steps"]
52 .as_array()
53 .expect("fixture steps")
54 .iter()
55 .enumerate()
56 {
57 let document = &step["document"];
58 let errors: Vec<_> = validator
59 .iter_errors(document)
60 .map(|error| error.to_string())
61 .collect();
62 assert!(
63 errors.is_empty(),
64 "{id} step {index} violates the public ORM schema: {errors:?}"
65 );
66 }
67 }
68 }
69
70 #[test]
71 fn conformance_fixtures_compile_to_the_published_sql_and_parameters() {
72 let artifact: serde_json::Value = serde_json::from_str(ORM_CONFORMANCE_FIXTURES).unwrap();
73 assert_eq!(
74 artifact["fixtures"],
75 serde_json::Value::String("radixdb.orm.fixtures.v1".to_string())
76 );
77 let cases = artifact["cases"].as_array().expect("fixture cases");
78 let mut fixture_ids = BTreeSet::new();
79 for case in cases {
80 let id = case["id"].as_str().expect("stable fixture id");
81 assert!(fixture_ids.insert(id), "duplicate fixture ID {id}");
82 let steps = case["steps"].as_array().expect("fixture steps");
83 assert!(!steps.is_empty(), "{id}: no executable steps");
84 for (index, step) in steps.iter().enumerate() {
85 let document = crate::IrDocument::from_json(
86 &serde_json::to_string(&step["document"]).unwrap(),
87 )
88 .unwrap_or_else(|error| panic!("{id} step {index}: invalid IR: {error}"));
89 let compiled = document
90 .to_sql()
91 .unwrap_or_else(|error| panic!("{id} step {index}: render failed: {error}"));
92 assert_eq!(
93 compiled.sql,
94 step["sql"].as_str().unwrap(),
95 "{id} step {index}"
96 );
97 assert_eq!(
98 serde_json::to_value(&compiled.parameters).unwrap(),
99 step["parameters"],
100 "{id} step {index}"
101 );
102 }
103 if let Some(rejections) = case.get("rejected_documents") {
104 for rejected in rejections.as_array().expect("rejection cases") {
105 assert!(
106 crate::IrDocument::from_json(&serde_json::to_string(rejected).unwrap())
107 .is_err(),
108 "{id}: rejection unexpectedly decoded"
109 );
110 }
111 }
112 assert!(case.get("result").is_some(), "{id}: missing result oracle");
113 }
114
115 for id in [
116 "ORM-CONFORMANCE-001",
117 "ORM-CONFORMANCE-002",
118 "ORM-CONFORMANCE-003",
119 ] {
120 assert!(fixture_ids.contains(id), "missing base fixture {id}");
121 }
122 }
123}