rave_engine 0.8.0

A secure and efficient JSON Schema validation and Rhai script execution engine
Documentation
#[cfg(test)]
mod tests {
    use crate::json_schema_validator::*;
    use serde_json::json;

    // Test: Valid schema
    #[test]
    fn test_valid_schema() {
        let schema = json!({
            "type": "object",
            "properties": {
                "name": { "type": "string" },
                "age": { "type": "integer" }
            },
            "required": ["name", "age"]
        });

        let result = is_valid_schema(&schema);
        assert_eq!(result, Ok(()));
    }

    // Test: Invalid schema (missing 'type')
    #[test]
    fn test_invalid_schema_missing_type() {
        let schema = json!({
            "properties": {
                "name": { "type": "string" },
                "age": { "type": "integer" }
            }
        });

        let result = is_valid_schema(&schema);
        assert_eq!(result, Err("Schema must contain a 'type'".to_string()));
    }

    // Test: Invalid schema (unsupported type)
    #[test]
    fn test_invalid_schema_unsupported_type() {
        let schema = json!({
            "type": "unsupported_type",
            "properties": {
                "name": { "type": "string" }
            }
        });

        let result = is_valid_schema(&schema);
        assert_eq!(
            result,
            Err("Unsupported schema type: unsupported_type".to_string())
        );
    }

    // Test: Valid instance against valid schema
    #[test]
    fn test_validate_json_schema_valid() {
        let schema = json!({
            "type": "object",
            "properties": {
                "name": { "type": "string" },
                "age": { "type": "integer" }
            },
            "required": ["name", "age"]
        });

        let instance = json!({
            "name": "John",
            "age": 30
        });

        let result = validate_json_schema(&schema, &instance);
        assert_eq!(result, Ok(()));
    }

    // Test: Invalid instance against valid schema
    #[test]
    fn test_validate_json_schema_invalid() {
        let schema = json!({
            "type": "object",
            "properties": {
                "name": { "type": "string" },
                "age": { "type": "integer" }
            },
            "required": ["name", "age"]
        });

        let instance = json!({
            "name": "John"
        });

        let result = validate_json_schema(&schema, &instance);
        assert_eq!(result, Err("Missing required field: age".to_string()));
    }

    // Test: Basic types validation
    #[test]
    fn test_basic_types() {
        let schema = json!({
            "type": "object",
            "properties": {
                "string_field": { "type": "string" },
                "number_field": { "type": "number" },
                "integer_field": { "type": "integer" },
                "boolean_field": { "type": "boolean" },
                "null_field": { "type": "null" },
                "array_field": { "type": "array" }
            }
        });

        let valid_instance = json!({
            "string_field": "test",
            "number_field": 10.5,
            "integer_field": 42,
            "boolean_field": true,
            "null_field": null,
            "array_field": [1, 2, 3]
        });

        assert_eq!(validate_json_schema(&schema, &valid_instance), Ok(()));

        let invalid_instance = json!({
            "string_field": 123,  // wrong type
            "number_field": "10.5", // wrong type
            "integer_field": 42.5,  // not an integer
            "boolean_field": "true", // wrong type
            "null_field": 0,        // wrong type
            "array_field": "not an array" // wrong type
        });

        assert!(validate_json_schema(&schema, &invalid_instance).is_err());
    }

    // Test: Array validation
    #[test]
    fn test_array_validation() {
        let schema = json!({
            "type": "array",
            "items": { "type": "string" },
            "minItems": 2,
            "maxItems": 4,
            "uniqueItems": true
        });

        let valid_instance = json!(["a", "b", "c"]);
        assert_eq!(validate_json_schema(&schema, &valid_instance), Ok(()));

        let invalid_length = json!(["a"]);
        assert!(validate_json_schema(&schema, &invalid_length).is_err());

        let invalid_type = json!([1, "b", "c"]);
        assert!(validate_json_schema(&schema, &invalid_type).is_err());

        let duplicate_items = json!(["a", "a", "b"]);
        assert!(validate_json_schema(&schema, &duplicate_items).is_err());
    }

    // Test: Number constraints
    #[test]
    fn test_number_constraints() {
        let schema = json!({
            "type": "object",
            "properties": {
                "value": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100,
                    "multipleOf": 5
                }
            }
        });

        let valid_instance = json!({ "value": 25 });
        assert_eq!(validate_json_schema(&schema, &valid_instance), Ok(()));

        let invalid_min = json!({ "value": -1 });
        assert!(validate_json_schema(&schema, &invalid_min).is_err());

        let invalid_max = json!({ "value": 101 });
        assert!(validate_json_schema(&schema, &invalid_max).is_err());

        let invalid_multiple = json!({ "value": 27 });
        assert!(validate_json_schema(&schema, &invalid_multiple).is_err());
    }

    // Test: String constraints
    #[test]
    fn test_string_constraints() {
        let schema = json!({
            "type": "object",
            "properties": {
                "value": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 10,
                    "pattern": "^[A-Za-z]+$"
                }
            }
        });

        let valid_instance = json!({ "value": "Hello" });
        assert_eq!(validate_json_schema(&schema, &valid_instance), Ok(()));

        let invalid_min_length = json!({ "value": "ab" });
        assert!(validate_json_schema(&schema, &invalid_min_length).is_err());

        let invalid_max_length = json!({ "value": "toolongstring" });
        assert!(validate_json_schema(&schema, &invalid_max_length).is_err());

        let invalid_pattern = json!({ "value": "Hello123" });
        assert!(validate_json_schema(&schema, &invalid_pattern).is_err());
    }

    // Test: Nested array validation
    #[test]
    fn test_nested_array_validation() {
        let schema = json!({
            "type": "object",
            "properties": {
                "unyt_allocation": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "agent": { "type": "string" },
                            "amount": {
                                "type": "array",
                                "items": { "type": "number" }
                            }
                        },
                        "required": ["agent", "amount"]
                    }
                }
            },
            "required": ["unyt_allocation"]
        });

        let valid_instance = json!({
            "unyt_allocation": [{
                "agent": "uhCAkL9ry68Urot_86esnhqYjPJqTCXC5Te403Ho7s_QNM4Jtr9eT",
                "amount": [10]
            }]
        });

        let result = validate_json_schema(&schema, &valid_instance);
        assert_eq!(result, Ok(()));

        let invalid_instance = json!({
            "unyt_allocation": [{
                "agent": "uhCAkL9ry68Urot_86esnhqYjPJqTCXC5Te403Ho7s_QNM4Jtr9eT",
                "amount": ["10"]  // string instead of number
            }]
        });

        let result = validate_json_schema(&schema, &invalid_instance);
        assert!(result.is_err());
    }
}