"""Tests for the execution audit trail module. Validates audit event construction, event type constants, and the convenience helpers that record each stage of the execution pipeline. """ from services.shared.audit import ( AUDIT_ORDER_CANCELLED, AUDIT_ORDER_DUPLICATE, AUDIT_ORDER_FILLED, AUDIT_ORDER_REJECTED, AUDIT_ORDER_SUBMITTED, AUDIT_POSITION_CLOSED, AUDIT_POSITION_OPENED, AUDIT_POSITION_UPDATED, AUDIT_RECOMMENDATION_GENERATED, AUDIT_RECOMMENDATION_SUPPRESSED, AUDIT_RISK_EVALUATED, AUDIT_RISK_REJECTED, AUDIT_TRADING_MODE_CHANGED, ) # --------------------------------------------------------------------------- # Event type constants # --------------------------------------------------------------------------- class TestAuditEventTypes: """Verify event type constants are well-formed and distinct.""" def test_recommendation_events(self): assert AUDIT_RECOMMENDATION_GENERATED == "recommendation.generated" assert AUDIT_RECOMMENDATION_SUPPRESSED == "recommendation.suppressed" def test_risk_events(self): assert AUDIT_RISK_EVALUATED == "risk.evaluated" assert AUDIT_RISK_REJECTED == "risk.rejected" def test_order_events(self): assert AUDIT_ORDER_SUBMITTED == "order.submitted" assert AUDIT_ORDER_FILLED == "order.filled" assert AUDIT_ORDER_REJECTED == "order.rejected" assert AUDIT_ORDER_CANCELLED == "order.cancelled" assert AUDIT_ORDER_DUPLICATE == "order.duplicate_prevented" def test_position_events(self): assert AUDIT_POSITION_OPENED == "position.opened" assert AUDIT_POSITION_CLOSED == "position.closed" assert AUDIT_POSITION_UPDATED == "position.updated" def test_trading_mode_event(self): assert AUDIT_TRADING_MODE_CHANGED == "trading.mode_changed" def test_all_event_types_unique(self): all_types = [ AUDIT_RECOMMENDATION_GENERATED, AUDIT_RECOMMENDATION_SUPPRESSED, AUDIT_RISK_EVALUATED, AUDIT_RISK_REJECTED, AUDIT_ORDER_SUBMITTED, AUDIT_ORDER_FILLED, AUDIT_ORDER_REJECTED, AUDIT_ORDER_CANCELLED, AUDIT_ORDER_DUPLICATE, AUDIT_POSITION_OPENED, AUDIT_POSITION_CLOSED, AUDIT_POSITION_UPDATED, AUDIT_TRADING_MODE_CHANGED, ] assert len(all_types) == len(set(all_types)) def test_event_types_follow_dot_notation(self): """All event types should follow entity.action pattern.""" all_types = [ AUDIT_RECOMMENDATION_GENERATED, AUDIT_RECOMMENDATION_SUPPRESSED, AUDIT_RISK_EVALUATED, AUDIT_RISK_REJECTED, AUDIT_ORDER_SUBMITTED, AUDIT_ORDER_FILLED, AUDIT_ORDER_REJECTED, AUDIT_ORDER_CANCELLED, AUDIT_ORDER_DUPLICATE, AUDIT_POSITION_OPENED, AUDIT_POSITION_CLOSED, AUDIT_POSITION_UPDATED, AUDIT_TRADING_MODE_CHANGED, ] for t in all_types: assert "." in t, f"Event type {t} should use dot notation" parts = t.split(".") assert len(parts) == 2, f"Event type {t} should have exactly one dot" assert all(p for p in parts), f"Event type {t} has empty parts" # --------------------------------------------------------------------------- # Module imports and structure # --------------------------------------------------------------------------- class TestAuditModuleStructure: """Verify the audit module exports the expected functions.""" def test_record_audit_event_exists(self): from services.shared.audit import record_audit_event assert callable(record_audit_event) def test_convenience_helpers_exist(self): from services.shared.audit import ( audit_duplicate_prevented, audit_order_cancelled, audit_order_filled, audit_order_rejected, audit_order_submitted, audit_position_change, audit_recommendation_generated, audit_risk_evaluated, audit_trading_mode_changed, ) for fn in [ audit_recommendation_generated, audit_risk_evaluated, audit_order_submitted, audit_order_filled, audit_order_rejected, audit_order_cancelled, audit_duplicate_prevented, audit_position_change, audit_trading_mode_changed, ]: assert callable(fn) def test_query_helpers_exist(self): from services.shared.audit import ( get_entity_audit_trail, get_order_audit_trail, ) assert callable(get_order_audit_trail) assert callable(get_entity_audit_trail) # --------------------------------------------------------------------------- # Broker service audit integration # --------------------------------------------------------------------------- class TestBrokerServiceAuditImports: """Verify the broker service uses audit functions from the audit module.""" def test_broker_service_has_audit_calls(self): """The broker service module should reference audit functions.""" import inspect import services.adapters.broker_service as bs source = inspect.getsource(bs) assert "audit_order_submitted" in source assert "audit_order_filled" in source assert "audit_order_rejected" in source assert "audit_risk_evaluated" in source assert "audit_duplicate_prevented" in source