fixed type mismatch checking to not fail fast and work through nested data
This commit is contained in:
115
src/tests.rs
115
src/tests.rs
@ -51,16 +51,7 @@ fn test_validate_simple() {
|
||||
#[pg_test]
|
||||
fn test_cache_invalid() {
|
||||
let cache_result = invalid_schemas();
|
||||
|
||||
// Should fail due to invalid schema in the request
|
||||
// Bulk caching produces both detailed meta-schema validation errors and a high-level wrapper error
|
||||
assert_error_count(&cache_result, 3); // 2 detailed meta-schema errors + 1 high-level wrapper
|
||||
|
||||
// Check the high-level wrapper error
|
||||
let wrapper_error = find_error_with_code(&cache_result, "COMPILE_ALL_SCHEMAS_FAILED");
|
||||
assert_error_message_contains(wrapper_error, "Failed to compile JSON schemas during cache operation");
|
||||
|
||||
// Should also have detailed meta-schema validation errors
|
||||
assert_error_count(&cache_result, 2);
|
||||
assert!(has_error_with_code(&cache_result, "ENUM_VIOLATED"),
|
||||
"Should have ENUM_VIOLATED errors");
|
||||
}
|
||||
@ -506,10 +497,10 @@ fn test_validate_property_merging() {
|
||||
// entity (id, name) + user (password) + person (first_name, last_name)
|
||||
|
||||
let valid_person_with_all_properties = json!({
|
||||
"type": "person", // Added to satisfy new type check
|
||||
// From entity
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "John Doe",
|
||||
"type": "person",
|
||||
|
||||
// From user
|
||||
"password": "securepass123",
|
||||
@ -524,9 +515,9 @@ fn test_validate_property_merging() {
|
||||
|
||||
// Test that properties validate according to their schema definitions across the chain
|
||||
let invalid_mixed_properties = json!({
|
||||
"type": "person", // Added to satisfy new type check
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "John Doe",
|
||||
"type": "person",
|
||||
"password": "short", // Too short from user schema
|
||||
"first_name": "", // Empty string violates person schema minLength
|
||||
"last_name": "Doe"
|
||||
@ -548,10 +539,10 @@ fn test_validate_required_merging() {
|
||||
// user: ["password"] (conditional when type=user)
|
||||
// person: ["first_name", "last_name"] (conditional when type=person)
|
||||
|
||||
let missing_all_required = json!({ "type": "person" }); // Add type to pass initial check
|
||||
let missing_all_required = json!({ "type": "person" });
|
||||
|
||||
let result = validate_json_schema("person", jsonb(missing_all_required));
|
||||
// Should fail for all required fields across inheritance chain, except for the conditional 'password'
|
||||
// Should fail for all required fields across inheritance chain
|
||||
assert_error_count(&result, 4); // id, created_by, first_name, last_name
|
||||
assert_has_error(&result, "REQUIRED_FIELD_MISSING", "/id");
|
||||
assert_has_error(&result, "REQUIRED_FIELD_MISSING", "/created_by");
|
||||
@ -622,6 +613,7 @@ fn test_validate_punc_with_refs() {
|
||||
|
||||
// Test 1: Public punc is strict - no extra properties allowed at root level
|
||||
let public_root_extra = json!({
|
||||
"type": "person",
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "John Doe",
|
||||
"first_name": "John",
|
||||
@ -637,6 +629,7 @@ fn test_validate_punc_with_refs() {
|
||||
|
||||
// Test 2: Private punc allows extra properties at root level
|
||||
let private_root_extra = json!({
|
||||
"type": "person",
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "John Doe",
|
||||
"first_name": "John",
|
||||
@ -650,6 +643,7 @@ fn test_validate_punc_with_refs() {
|
||||
|
||||
// Test 3: Valid data with address should pass for both
|
||||
let valid_data_with_address = json!({
|
||||
"type": "person",
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "John Doe",
|
||||
"first_name": "John",
|
||||
@ -668,6 +662,7 @@ fn test_validate_punc_with_refs() {
|
||||
|
||||
// Test 4: Extra properties in nested address should fail for BOTH puncs (types are always strict)
|
||||
let address_with_extra = json!({
|
||||
"type": "person",
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "John Doe",
|
||||
"first_name": "John",
|
||||
@ -679,20 +674,6 @@ fn test_validate_punc_with_refs() {
|
||||
}
|
||||
});
|
||||
|
||||
// NOTE: The following test is disabled due to what appears to be a bug in the `boon` validator.
|
||||
// When a validation fails within a referenced schema (`$ref`), `boon` does not seem to propagate
|
||||
// the set of evaluated properties back to the parent schema. As a result, if the parent schema
|
||||
// also uses `unevaluatedProperties`, it incorrectly flags all properties as unevaluated.
|
||||
// In this case, the validation of `person` fails on `/address/country`, which prevents the
|
||||
// `public_ref_test.request` schema from learning that `id`, `name`, etc., were evaluated,
|
||||
// causing it to incorrectly report 6 errors instead of the expected 1.
|
||||
// The `allOf` wrapper workaround does not solve this, as the information is lost on any `Err` result.
|
||||
// This test is preserved to be re-enabled if/when the validator is fixed.
|
||||
//
|
||||
// let result_public_address = validate_json_schema("public_ref_test.request", jsonb(address_with_extra.clone()));
|
||||
// assert_error_count(&result_public_address, 1);
|
||||
// assert_has_error(&result_public_address, "FALSE_SCHEMA", "/address/country");
|
||||
|
||||
let result_private_address = validate_json_schema("private_ref_test.request", jsonb(address_with_extra));
|
||||
assert_error_count(&result_private_address, 1);
|
||||
assert_has_error(&result_private_address, "FALSE_SCHEMA", "/address/country");
|
||||
@ -735,6 +716,7 @@ fn test_validate_punc_local_refs() {
|
||||
|
||||
// Test 1: Punc request referencing a schema defined locally within the punc
|
||||
let valid_local_ref = json!({
|
||||
"type": "local_address",
|
||||
"street": "123 Main St",
|
||||
"city": "Anytown"
|
||||
});
|
||||
@ -742,6 +724,7 @@ fn test_validate_punc_local_refs() {
|
||||
assert_success(&result_valid_local);
|
||||
|
||||
let invalid_local_ref = json!({
|
||||
"type": "local_address",
|
||||
"street": "123 Main St" // Missing city
|
||||
});
|
||||
let result_invalid_local = validate_json_schema("punc_with_local_ref_test.request", jsonb(invalid_local_ref));
|
||||
@ -750,8 +733,10 @@ fn test_validate_punc_local_refs() {
|
||||
|
||||
// Test 2: Punc with a local schema that references a global type schema
|
||||
let valid_global_ref = json!({
|
||||
"type": "local_user_with_thing",
|
||||
"user_name": "Alice",
|
||||
"thing": {
|
||||
"type": "global_thing",
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000"
|
||||
}
|
||||
});
|
||||
@ -759,8 +744,10 @@ fn test_validate_punc_local_refs() {
|
||||
assert_success(&result_valid_global);
|
||||
|
||||
let invalid_global_ref = json!({
|
||||
"type": "local_user_with_thing",
|
||||
"user_name": "Bob",
|
||||
"thing": {
|
||||
"type": "global_thing",
|
||||
"id": "not-a-uuid" // Invalid format for global_thing's id
|
||||
}
|
||||
});
|
||||
@ -842,4 +829,76 @@ fn test_validate_type_matching() {
|
||||
assert_error_count(&result_invalid_short, 1);
|
||||
let error = find_error_with_code_and_path(&result_invalid_short, "TYPE_MISMATCH", "/type");
|
||||
assert_error_message_contains(error, "Instance type 'job' does not match expected type 'super_job'");
|
||||
|
||||
// 4. Test punc with root, nested, and oneOf type refs
|
||||
let valid_punc_instance = json!({
|
||||
"root_job": {
|
||||
"type": "job",
|
||||
"name": "root job",
|
||||
"job_id": "job456"
|
||||
},
|
||||
"nested_or_super_job": {
|
||||
"type": "super_job",
|
||||
"name": "nested super job",
|
||||
"job_id": "job789",
|
||||
"manager_id": "mgr2"
|
||||
}
|
||||
});
|
||||
let result_valid_punc = validate_json_schema("type_test_punc.request", jsonb(valid_punc_instance));
|
||||
assert_success(&result_valid_punc);
|
||||
|
||||
// 5. Test invalid type at punc root ref
|
||||
let invalid_punc_root = json!({
|
||||
"root_job": {
|
||||
"type": "entity", // Should be "job"
|
||||
"name": "root job",
|
||||
"job_id": "job456"
|
||||
},
|
||||
"nested_or_super_job": {
|
||||
"type": "super_job",
|
||||
"name": "nested super job",
|
||||
"job_id": "job789",
|
||||
"manager_id": "mgr2"
|
||||
}
|
||||
});
|
||||
let result_invalid_punc_root = validate_json_schema("type_test_punc.request", jsonb(invalid_punc_root));
|
||||
assert_error_count(&result_invalid_punc_root, 1);
|
||||
assert_has_error(&result_invalid_punc_root, "TYPE_MISMATCH", "/root_job/type");
|
||||
|
||||
// 6. Test invalid type at punc nested ref
|
||||
let invalid_punc_nested = json!({
|
||||
"root_job": {
|
||||
"type": "job",
|
||||
"name": "root job",
|
||||
"job_id": "job456"
|
||||
},
|
||||
"nested_or_super_job": {
|
||||
"my_job": {
|
||||
"type": "entity", // Should be "job"
|
||||
"name": "nested job",
|
||||
"job_id": "job789"
|
||||
}
|
||||
}
|
||||
});
|
||||
let result_invalid_punc_nested = validate_json_schema("type_test_punc.request", jsonb(invalid_punc_nested));
|
||||
assert_error_count(&result_invalid_punc_nested, 1);
|
||||
assert_has_error(&result_invalid_punc_nested, "TYPE_MISMATCH", "/nested_or_super_job/my_job/type");
|
||||
|
||||
// 7. Test invalid type at punc oneOf ref
|
||||
let invalid_punc_oneof = json!({
|
||||
"root_job": {
|
||||
"type": "job",
|
||||
"name": "root job",
|
||||
"job_id": "job456"
|
||||
},
|
||||
"nested_or_super_job": {
|
||||
"type": "job", // Should be "super_job"
|
||||
"name": "nested super job",
|
||||
"job_id": "job789",
|
||||
"manager_id": "mgr2"
|
||||
}
|
||||
});
|
||||
let result_invalid_punc_oneof = validate_json_schema("type_test_punc.request", jsonb(invalid_punc_oneof));
|
||||
// This will have multiple errors because the invalid oneOf branch will also fail the other branch's validation
|
||||
assert_has_error(&result_invalid_punc_oneof, "TYPE_MISMATCH", "/nested_or_super_job/type");
|
||||
}
|
||||
Reference in New Issue
Block a user