"""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