232 lines
7.5 KiB
Python
232 lines
7.5 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
JSON Schema Validator Test Module
|
|
|
|
Unit tests for ddms_compliance_suite.json_schema_validator.validator module,
|
|
validates JSON data against schema definitions.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import unittest
|
|
import json
|
|
from unittest import mock
|
|
from pathlib import Path
|
|
|
|
# Add project root to Python path
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
|
|
# Import classes and functions to test
|
|
from ddms_compliance_suite.json_schema_validator.validator import JSONSchemaValidator
|
|
from ddms_compliance_suite.models.rule_models import JSONSchemaDefinition, RuleCategory, TargetType
|
|
|
|
class TestJSONSchemaValidator(unittest.TestCase):
|
|
"""JSON Schema Validator Test Class"""
|
|
|
|
def setUp(self):
|
|
"""Setup before tests"""
|
|
# Create validator instance
|
|
self.validator = JSONSchemaValidator()
|
|
|
|
# Test schema definition
|
|
self.well_schema = {
|
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
"type": "object",
|
|
"required": ["wellName", "wellID", "status", "coordinates"],
|
|
"properties": {
|
|
"wellName": {
|
|
"type": "string",
|
|
"description": "Well name"
|
|
},
|
|
"wellID": {
|
|
"type": "string",
|
|
"pattern": "^W[0-9]{10}$",
|
|
"description": "Well unique identifier, must be W followed by 10 digits"
|
|
},
|
|
"status": {
|
|
"type": "string",
|
|
"enum": ["active", "inactive", "abandoned", "suspended"],
|
|
"description": "Current well status"
|
|
},
|
|
"coordinates": {
|
|
"type": "object",
|
|
"required": ["longitude", "latitude"],
|
|
"properties": {
|
|
"longitude": {
|
|
"type": "number",
|
|
"minimum": -180,
|
|
"maximum": 180,
|
|
"description": "Longitude coordinate"
|
|
},
|
|
"latitude": {
|
|
"type": "number",
|
|
"minimum": -90,
|
|
"maximum": 90,
|
|
"description": "Latitude coordinate"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Create a schema rule
|
|
self.schema_rule = JSONSchemaDefinition(
|
|
id="well-data-schema",
|
|
name="Well Data Schema",
|
|
description="Defines JSON structure for well data",
|
|
category=RuleCategory.JSON_SCHEMA,
|
|
version="1.0.0",
|
|
target_type=TargetType.DATA_OBJECT,
|
|
target_identifier="Well",
|
|
schema_content=self.well_schema
|
|
)
|
|
|
|
def test_valid_data(self):
|
|
"""Test that valid data passes validation"""
|
|
# Valid test data
|
|
valid_data = {
|
|
"wellName": "Test Well-01",
|
|
"wellID": "W0123456789",
|
|
"status": "active",
|
|
"coordinates": {
|
|
"longitude": 116.3833,
|
|
"latitude": 39.9167
|
|
}
|
|
}
|
|
|
|
# Validate
|
|
result = self.validator.validate(valid_data, self.well_schema)
|
|
|
|
# Assert
|
|
self.assertTrue(result.is_valid)
|
|
self.assertEqual(len(result.errors), 0)
|
|
|
|
def test_missing_required_field(self):
|
|
"""Test missing required field scenario"""
|
|
# Data missing required field
|
|
invalid_data = {
|
|
"wellName": "Test Well-01",
|
|
"wellID": "W0123456789",
|
|
# Missing status field
|
|
"coordinates": {
|
|
"longitude": 116.3833,
|
|
"latitude": 39.9167
|
|
}
|
|
}
|
|
|
|
# Validate
|
|
result = self.validator.validate(invalid_data, self.well_schema)
|
|
|
|
# Assert
|
|
self.assertFalse(result.is_valid)
|
|
self.assertTrue(any("status" in error for error in result.errors))
|
|
|
|
def test_invalid_pattern(self):
|
|
"""Test field with invalid pattern"""
|
|
# Data with invalid wellID format
|
|
invalid_data = {
|
|
"wellName": "Test Well-01",
|
|
"wellID": "ABCDEFGHIJK", # Does not match W + 10 digits pattern
|
|
"status": "active",
|
|
"coordinates": {
|
|
"longitude": 116.3833,
|
|
"latitude": 39.9167
|
|
}
|
|
}
|
|
|
|
# Validate
|
|
result = self.validator.validate(invalid_data, self.well_schema)
|
|
|
|
# Assert
|
|
self.assertFalse(result.is_valid)
|
|
self.assertTrue(any("pattern" in error for error in result.errors))
|
|
|
|
def test_invalid_enum(self):
|
|
"""Test value not in enum"""
|
|
# Data with status not in enum list
|
|
invalid_data = {
|
|
"wellName": "Test Well-01",
|
|
"wellID": "W0123456789",
|
|
"status": "unknown", # Not in enum list
|
|
"coordinates": {
|
|
"longitude": 116.3833,
|
|
"latitude": 39.9167
|
|
}
|
|
}
|
|
|
|
# Validate
|
|
result = self.validator.validate(invalid_data, self.well_schema)
|
|
|
|
# Assert
|
|
self.assertFalse(result.is_valid)
|
|
self.assertTrue(any("enum" in error for error in result.errors))
|
|
|
|
def test_invalid_number_range(self):
|
|
"""Test number out of range"""
|
|
# Data with longitude out of range
|
|
invalid_data = {
|
|
"wellName": "Test Well-01",
|
|
"wellID": "W0123456789",
|
|
"status": "active",
|
|
"coordinates": {
|
|
"longitude": 200.0, # Outside [-180, 180] range
|
|
"latitude": 39.9167
|
|
}
|
|
}
|
|
|
|
# Validate
|
|
result = self.validator.validate(invalid_data, self.well_schema)
|
|
|
|
# Assert
|
|
self.assertFalse(result.is_valid)
|
|
self.assertTrue(any("maximum" in error for error in result.errors))
|
|
|
|
def test_validate_with_rule(self):
|
|
"""Test validation using rule object"""
|
|
# Valid test data
|
|
valid_data = {
|
|
"wellName": "Test Well-01",
|
|
"wellID": "W0123456789",
|
|
"status": "active",
|
|
"coordinates": {
|
|
"longitude": 116.3833,
|
|
"latitude": 39.9167
|
|
}
|
|
}
|
|
|
|
# Validate using rule object
|
|
result = self.validator.validate_with_rule(valid_data, self.schema_rule)
|
|
|
|
# Assert
|
|
self.assertTrue(result.is_valid)
|
|
self.assertEqual(len(result.errors), 0)
|
|
|
|
def test_additional_properties(self):
|
|
"""Test handling of additional properties"""
|
|
# Create a schema that prohibits additional properties
|
|
strict_schema = dict(self.well_schema)
|
|
strict_schema["additionalProperties"] = False
|
|
|
|
# Data with extra property
|
|
data_with_extra = {
|
|
"wellName": "Test Well-01",
|
|
"wellID": "W0123456789",
|
|
"status": "active",
|
|
"coordinates": {
|
|
"longitude": 116.3833,
|
|
"latitude": 39.9167
|
|
},
|
|
"extra_field": "Extra Field" # Extra field
|
|
}
|
|
|
|
# Validate
|
|
result = self.validator.validate(data_with_extra, strict_schema)
|
|
|
|
# Assert
|
|
self.assertFalse(result.is_valid)
|
|
self.assertTrue(any("additionalProperties" in error for error in result.errors))
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main() |