queryer merger test progress
This commit is contained in:
@ -4,7 +4,6 @@ pub mod context;
|
||||
pub mod error;
|
||||
pub mod result;
|
||||
pub mod rules;
|
||||
pub mod util;
|
||||
|
||||
pub use context::ValidationContext;
|
||||
pub use error::ValidationError;
|
||||
@ -46,11 +45,7 @@ impl Validator {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate(
|
||||
&self,
|
||||
schema_id: &str,
|
||||
instance: &Value,
|
||||
) -> Result<ValidationResult, ValidationError> {
|
||||
pub fn validate(&self, schema_id: &str, instance: &Value) -> crate::drop::Drop {
|
||||
if let Some(schema) = self.db.schemas.get(schema_id) {
|
||||
let ctx = ValidationContext::new(
|
||||
&self.db,
|
||||
@ -61,13 +56,37 @@ impl Validator {
|
||||
false,
|
||||
false,
|
||||
);
|
||||
ctx.validate_scoped()
|
||||
match ctx.validate_scoped() {
|
||||
Ok(result) => {
|
||||
if result.is_valid() {
|
||||
crate::drop::Drop::success()
|
||||
} else {
|
||||
let errors: Vec<crate::drop::Error> = result
|
||||
.errors
|
||||
.into_iter()
|
||||
.map(|e| crate::drop::Error {
|
||||
code: e.code,
|
||||
message: e.message,
|
||||
details: crate::drop::ErrorDetails { path: e.path },
|
||||
})
|
||||
.collect();
|
||||
crate::drop::Drop::with_errors(errors)
|
||||
}
|
||||
}
|
||||
Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
code: e.code,
|
||||
message: e.message,
|
||||
details: crate::drop::ErrorDetails { path: e.path },
|
||||
}]),
|
||||
}
|
||||
} else {
|
||||
Err(ValidationError {
|
||||
crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
code: "SCHEMA_NOT_FOUND".to_string(),
|
||||
message: format!("Schema {} not found", schema_id),
|
||||
path: "".to_string(),
|
||||
})
|
||||
details: crate::drop::ErrorDetails {
|
||||
path: "".to_string(),
|
||||
},
|
||||
}])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,127 +0,0 @@
|
||||
use serde::Deserialize;
|
||||
use std::fs;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct TestSuite {
|
||||
#[allow(dead_code)]
|
||||
description: String,
|
||||
database: serde_json::Value,
|
||||
tests: Vec<TestCase>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct TestCase {
|
||||
pub description: String,
|
||||
|
||||
#[serde(default = "default_action")]
|
||||
pub action: String, // "validate", "merge", or "query"
|
||||
|
||||
// For Validate & Query
|
||||
#[serde(default)]
|
||||
pub schema_id: String,
|
||||
|
||||
// For Query
|
||||
#[serde(default)]
|
||||
pub stem: Option<String>,
|
||||
|
||||
#[serde(default)]
|
||||
pub filters: Option<serde_json::Value>,
|
||||
|
||||
// For Merge & Validate
|
||||
#[serde(default)]
|
||||
pub data: Option<serde_json::Value>,
|
||||
|
||||
// For Merge & Query mocks
|
||||
#[serde(default)]
|
||||
pub mocks: Option<serde_json::Value>,
|
||||
|
||||
pub expect: Option<ExpectBlock>,
|
||||
|
||||
// Legacy support for older tests to avoid migrating them all instantly
|
||||
pub valid: Option<bool>,
|
||||
pub expect_errors: Option<Vec<serde_json::Value>>,
|
||||
}
|
||||
|
||||
fn default_action() -> String {
|
||||
"validate".to_string()
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct ExpectBlock {
|
||||
pub success: bool,
|
||||
pub result: Option<serde_json::Value>,
|
||||
pub errors: Option<Vec<serde_json::Value>>,
|
||||
pub sql_patterns: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
// use crate::validator::registry::REGISTRY; // No longer used directly for tests!
|
||||
use crate::validator::Validator;
|
||||
use serde_json::Value;
|
||||
|
||||
pub fn deserialize_some<'de, D>(deserializer: D) -> Result<Option<Value>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let v = Value::deserialize(deserializer)?;
|
||||
Ok(Some(v))
|
||||
}
|
||||
|
||||
pub fn run_test_file_at_index(path: &str, index: usize) -> Result<(), String> {
|
||||
let content =
|
||||
fs::read_to_string(path).unwrap_or_else(|_| panic!("Failed to read file: {}", path));
|
||||
let suite: Vec<TestSuite> = serde_json::from_str(&content)
|
||||
.unwrap_or_else(|e| panic!("Failed to parse JSON in {}: {}", path, e));
|
||||
|
||||
if index >= suite.len() {
|
||||
panic!("Index {} out of bounds for file {}", index, path);
|
||||
}
|
||||
|
||||
let group = &suite[index];
|
||||
let mut failures = Vec::<String>::new();
|
||||
|
||||
let db_json = group.database.clone();
|
||||
let db = crate::database::Database::new(&db_json);
|
||||
let validator = Validator::new(std::sync::Arc::new(db));
|
||||
|
||||
// 4. Run Tests
|
||||
for test in group.tests.iter() {
|
||||
let schema_id = &test.schema_id;
|
||||
|
||||
if !validator.db.schemas.contains_key(schema_id) {
|
||||
failures.push(format!(
|
||||
"[{}] Missing Schema: Cannot find schema ID '{}'",
|
||||
group.description, schema_id
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
let result = validator.validate(schema_id, &test.data);
|
||||
|
||||
let (got_valid, _errors) = match &result {
|
||||
Ok(res) => (res.is_valid(), &res.errors),
|
||||
Err(_e) => {
|
||||
// If we encounter an execution error (e.g. Schema Not Found),
|
||||
// we treat it as a test failure.
|
||||
(false, &vec![])
|
||||
}
|
||||
};
|
||||
|
||||
if got_valid != test.valid {
|
||||
let error_msg = match &result {
|
||||
Ok(res) => format!("{:?}", res.errors),
|
||||
Err(e) => format!("Execution Error: {:?}", e),
|
||||
};
|
||||
|
||||
failures.push(format!(
|
||||
"[{}] Test '{}' failed. Expected: {}, Got: {}. Errors: {}",
|
||||
group.description, test.description, test.valid, got_valid, error_msg
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if !failures.is_empty() {
|
||||
return Err(failures.join("\n"));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user