Initial commit
Some checks failed
CI/CD Pipeline / Code Quality & Linting (push) Has been cancelled
CI/CD Pipeline / Policy Validation (push) Has been cancelled
CI/CD Pipeline / Test Suite (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-coverage) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-extract) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-firm-connectors) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-forms) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-hmrc) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-ingestion) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-kg) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-normalize-map) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-ocr) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-rag-indexer) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-rag-retriever) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-reason) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-rpa) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (ui-review) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-coverage) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-extract) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-kg) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-rag-retriever) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (ui-review) (push) Has been cancelled
CI/CD Pipeline / Generate SBOM (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Notifications (push) Has been cancelled

This commit is contained in:
harkon
2025-10-11 08:41:36 +01:00
commit b324ff09ef
276 changed files with 55220 additions and 0 deletions

View File

@@ -0,0 +1,270 @@
"""Unit tests for predicate compilation and DSL parsing."""
# FILE: tests/unit/coverage/test_predicate_compilation.py
import pytest
from libs.policy import PolicyLoader
# pylint: disable=wrong-import-position,import-error,too-few-public-methods,global-statement
# pylint: disable=raise-missing-from,unused-argument,too-many-arguments,too-many-positional-arguments
# pylint: disable=too-many-locals,import-outside-toplevel
# mypy: disable-error-code=union-attr
# mypy: disable-error-code=no-untyped-def
class TestPredicateCompilation:
"""Test predicate compilation and DSL parsing"""
@pytest.fixture
def policy_loader(self):
"""Create policy loader for testing"""
return PolicyLoader()
def test_compile_exists_condition(self, policy_loader):
"""Test compilation of exists() conditions"""
condition = "exists(IncomeItem[type='Employment'])"
predicate = policy_loader._compile_condition(condition)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_compile_exists_condition_with_filters(self, policy_loader):
"""Test exists() with complex filters"""
condition = "exists(IncomeItem[type='SelfEmployment' AND turnover_lt_vat_threshold=true])"
predicate = policy_loader._compile_condition(condition)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_compile_property_conditions(self, policy_loader):
"""Test compilation of property conditions"""
conditions = [
"property_joint_ownership",
"candidate_FHL",
"claims_FTCR",
"claims_remittance_basis",
"received_estate_income",
]
for condition in conditions:
predicate = policy_loader._compile_condition(condition)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_compile_computed_conditions(self, policy_loader):
"""Test compilation of computed conditions"""
conditions = [
"turnover_lt_vat_threshold",
"turnover_ge_vat_threshold",
]
for condition in conditions:
predicate = policy_loader._compile_condition(condition)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_compile_taxpayer_flag_conditions(self, policy_loader):
"""Test compilation of taxpayer flag conditions"""
condition = "taxpayer_flag:has_employment"
predicate = policy_loader._compile_condition(condition)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_compile_filing_mode_conditions(self, policy_loader):
"""Test compilation of filing mode conditions"""
condition = "filing_mode:paper"
predicate = policy_loader._compile_condition(condition)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_compile_unknown_condition(self, policy_loader):
"""Test compilation of unknown condition defaults to False"""
condition = "unknown_condition_type"
predicate = policy_loader._compile_condition(condition)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert result is False # Unknown conditions default to False
def test_exists_predicate_creation(self, policy_loader):
"""Test exists predicate creation with different entity types"""
entity_types = [
"IncomeItem",
"ExpenseItem",
"PropertyAsset",
"TrustDistribution",
]
for entity_type in entity_types:
predicate = policy_loader._create_exists_predicate(
entity_type, "type='test'"
)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_property_predicate_creation(self, policy_loader):
"""Test property predicate creation"""
properties = [
"property_joint_ownership",
"candidate_FHL",
"claims_FTCR",
]
for prop in properties:
predicate = policy_loader._create_property_predicate(prop)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_computed_predicate_creation(self, policy_loader):
"""Test computed predicate creation"""
computations = [
"turnover_lt_vat_threshold",
"turnover_ge_vat_threshold",
]
for comp in computations:
predicate = policy_loader._create_computed_predicate(comp)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_flag_predicate_creation(self, policy_loader):
"""Test flag predicate creation"""
flags = [
"has_employment",
"is_self_employed_short",
"has_property_income",
"has_foreign_income",
]
for flag in flags:
predicate = policy_loader._create_flag_predicate(flag)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_filing_mode_predicate_creation(self, policy_loader):
"""Test filing mode predicate creation"""
modes = ["paper", "online", "agent"]
for mode in modes:
predicate = policy_loader._create_filing_mode_predicate(mode)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_exists_condition_regex_parsing(self, policy_loader):
"""Test regex parsing of exists conditions"""
test_cases = [
(
"exists(IncomeItem[type='Employment'])",
"IncomeItem",
"type='Employment'",
),
(
"exists(ExpenseItem[category='FinanceCosts'])",
"ExpenseItem",
"category='FinanceCosts'",
),
(
"exists(PropertyAsset[joint_ownership=true])",
"PropertyAsset",
"joint_ownership=true",
),
]
for condition, expected_entity, expected_filters in test_cases:
# Test that the regex matches correctly
import re
exists_match = re.match(r"exists\((\w+)\[([^\]]+)\]\)", condition)
assert exists_match is not None
assert exists_match.group(1) == expected_entity
assert exists_match.group(2) == expected_filters
def test_condition_whitespace_handling(self, policy_loader):
"""Test that conditions handle whitespace correctly"""
conditions_with_whitespace = [
" exists(IncomeItem[type='Employment']) ",
"\tproperty_joint_ownership\t",
"\n taxpayer_flag:has_employment \n",
]
for condition in conditions_with_whitespace:
predicate = policy_loader._compile_condition(condition)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_complex_exists_filters(self, policy_loader):
"""Test exists conditions with complex filter expressions"""
complex_conditions = [
"exists(IncomeItem[type='SelfEmployment' AND turnover_lt_vat_threshold=true])",
"exists(ExpenseItem[category='CapitalAllowances'])",
"exists(IncomeItem[type IN ['ForeignInterest','ForeignDividends']])",
]
for condition in complex_conditions:
predicate = policy_loader._compile_condition(condition)
assert callable(predicate)
result = predicate("T-001", "2024-25")
assert isinstance(result, bool)
def test_predicate_consistency(self, policy_loader):
"""Test that predicates return consistent results for same inputs"""
condition = "exists(IncomeItem[type='Employment'])"
predicate = policy_loader._compile_condition(condition)
# Call multiple times with same inputs
result1 = predicate("T-001", "2024-25")
result2 = predicate("T-001", "2024-25")
result3 = predicate("T-001", "2024-25")
# Should be consistent
assert result1 == result2 == result3
def test_predicate_different_inputs(self, policy_loader):
"""Test predicates with different input combinations"""
condition = "exists(IncomeItem[type='Employment'])"
predicate = policy_loader._compile_condition(condition)
# Test with different taxpayer IDs and tax years
test_inputs = [
("T-001", "2024-25"),
("T-002", "2024-25"),
("T-001", "2023-24"),
("T-999", "2025-26"),
]
for taxpayer_id, tax_year in test_inputs:
result = predicate(taxpayer_id, tax_year)
assert isinstance(result, bool)
def test_edge_case_conditions(self, policy_loader):
"""Test edge cases in condition parsing"""
edge_cases = [
"", # Empty string
" ", # Whitespace only
"exists()", # Empty exists
"exists(Entity[])", # Empty filter
"taxpayer_flag:", # Empty flag
"filing_mode:", # Empty mode
]
for condition in edge_cases:
predicate = policy_loader._compile_condition(condition)
assert callable(predicate)
# Should default to False for malformed conditions
result = predicate("T-001", "2024-25")
assert result is False