test contracts

This commit is contained in:
2026-02-26 19:40:00 +03:00
parent 81d62c1345
commit 36173c0880
35 changed files with 1811 additions and 759 deletions

View File

@@ -23,6 +23,21 @@ from src.core.logger import logger, belief_scope
# [DEF:IdMappingService:Class]
# @TIER: CRITICAL
# @PURPOSE: Service handling the cataloging and retrieval of remote Superset Integer IDs.
#
# @TEST_CONTRACT: IdMappingServiceModel ->
# {
# required_fields: {db_session: Session},
# invariants: [
# "sync_environment correctly creates or updates ResourceMapping records",
# "get_remote_id returns an integer or None",
# "get_remote_ids_batch returns a dictionary of valid UUIDs to integers"
# ]
# }
# @TEST_FIXTURE: valid_mapping_service -> {"db_session": "MockSession()"}
# @TEST_EDGE: sync_api_failure -> handles exception gracefully
# @TEST_EDGE: get_remote_id_not_found -> returns None
# @TEST_EDGE: get_batch_empty_list -> returns empty dict
# @TEST_INVARIANT: resilient_fetching -> verifies: [sync_api_failure]
class IdMappingService:
# [DEF:__init__:Function]

View File

@@ -19,6 +19,20 @@ from ..logger import belief_scope
# @TIER: CRITICAL
# @INVARIANT: logger is always a valid TaskLogger instance.
# @UX_STATE: Idle -> Active -> Complete
#
# @TEST_CONTRACT: TaskContextInit ->
# {
# required_fields: {task_id: str, add_log_fn: Callable, params: dict},
# optional_fields: {default_source: str},
# invariants: [
# "task_id matches initialized logger's task_id",
# "logger is a valid TaskLogger instance"
# ]
# }
# @TEST_FIXTURE: valid_context -> {"task_id": "123", "add_log_fn": lambda *args: None, "params": {"k": "v"}, "default_source": "plugin"}
# @TEST_EDGE: missing_task_id -> raises TypeError
# @TEST_EDGE: missing_add_log_fn -> raises TypeError
# @TEST_INVARIANT: logger_initialized -> verifies: [valid_context]
class TaskContext:
"""
Execution context provided to plugins during task execution.

View File

@@ -39,17 +39,20 @@ from ..logger import logger, belief_scope, should_log_task_level
# @INVARIANT: Task IDs are unique within the registry.
# @INVARIANT: Each task has exactly one status at any time.
# @INVARIANT: Log entries are never deleted after being added to a task.
# @TEST_CONTRACT: TaskManager -> {
# required_fields: {plugin_id: str, params: dict},
# optional_fields: {user_id: str},
# invariants: ["Task IDs are unique within the registry", "Each task has exactly one status at any time"]
#
# @TEST_CONTRACT: TaskManagerModel ->
# {
# required_fields: {plugin_loader: PluginLoader},
# invariants: [
# "Tasks are persisted immediately upon creation",
# "Running tasks use a thread pool or asyncio event loop based on executor type",
# "Log flushing runs on a background thread"
# ]
# }
# @TEST_FIXTURE: create_valid_task -> {"plugin_id": "migration_plugin", "params": {"source": "A", "target": "B"}}
# @TEST_EDGE: missing_required_field -> {"plugin_id": null}
# @TEST_EDGE: empty_response -> {"params": {}}
# @TEST_EDGE: invalid_type -> {"params": "string_instead_of_dict"}
# @TEST_EDGE: external_failure -> {"plugin_not_found": true}
# @TEST_INVARIANT: single_status -> verifies: [create_valid_task, external_failure]
# @TEST_FIXTURE: valid_manager -> {"plugin_loader": "MockPluginLoader()"}
# @TEST_EDGE: create_task_invalid_plugin -> raises ValueError
# @TEST_EDGE: create_task_invalid_params -> raises ValueError
# @TEST_INVARIANT: lifecycle_management -> verifies: [valid_manager]
"""
Manages the lifecycle of tasks, including their creation, execution, and state tracking.
"""

View File

@@ -45,6 +45,14 @@ class LogLevel(str, Enum):
# @PURPOSE: A Pydantic model representing a single, structured log entry associated with a task.
# @TIER: CRITICAL
# @INVARIANT: Each log entry has a unique timestamp and source.
#
# @TEST_CONTRACT: LogEntryModel ->
# {
# required_fields: {message: str},
# optional_fields: {timestamp: datetime, level: str, source: str, context: dict, metadata: dict}
# }
# @TEST_FIXTURE: valid_log_entry -> {"message": "Plugin initialized"}
# @TEST_EDGE: empty_message -> {"message": ""}
class LogEntry(BaseModel):
timestamp: datetime = Field(default_factory=datetime.utcnow)
level: str = Field(default="INFO")

View File

@@ -24,6 +24,20 @@ from ..logger import logger, belief_scope
# @SEMANTICS: persistence, service, database, sqlalchemy
# @PURPOSE: Provides methods to save and load tasks from the tasks.db database using SQLAlchemy.
# @INVARIANT: Persistence must handle potentially missing task fields natively.
#
# @TEST_CONTRACT: TaskPersistenceService ->
# {
# required_fields: {},
# invariants: [
# "persist_task creates or updates a record",
# "load_tasks retrieves valid Task instances",
# "delete_tasks correctly removes records from the database"
# ]
# }
# @TEST_FIXTURE: valid_task_persistence -> {"task_id": "123", "status": "PENDING"}
# @TEST_EDGE: persist_invalid_task_type -> raises Exception
# @TEST_EDGE: load_corrupt_json_params -> handled gracefully
# @TEST_INVARIANT: accurate_round_trip -> verifies: [valid_task_persistence, load_corrupt_json_params]
class TaskPersistenceService:
# [DEF:_json_load_if_needed:Function]
# @PURPOSE: Safely load JSON strings from DB if necessary
@@ -245,6 +259,19 @@ class TaskPersistenceService:
# @TIER: CRITICAL
# @RELATION: DEPENDS_ON -> TaskLogRecord
# @INVARIANT: Log entries are batch-inserted for performance.
#
# @TEST_CONTRACT: TaskLogPersistenceService ->
# {
# required_fields: {},
# invariants: [
# "add_logs efficiently saves logs to the database",
# "get_logs retrieves properly filtered LogEntry objects"
# ]
# }
# @TEST_FIXTURE: valid_log_batch -> {"task_id": "123", "logs": [{"level": "INFO", "message": "msg"}]}
# @TEST_EDGE: empty_log_list -> no-op behavior
# @TEST_EDGE: add_logs_db_error -> rollback and log error
# @TEST_INVARIANT: accurate_log_aggregation -> verifies: [valid_log_batch]
class TaskLogPersistenceService:
"""
Service for persisting and querying task logs.

View File

@@ -15,8 +15,21 @@ from typing import Dict, Any, Optional, Callable
# @PURPOSE: A wrapper around TaskManager._add_log that carries task_id and source context.
# @TIER: CRITICAL
# @INVARIANT: All log calls include the task_id and source.
# @TEST_DATA: task_logger -> {"task_id": "test_123", "source": "test_plugin"}
# @UX_STATE: Idle -> Logging -> (system records log)
#
# @TEST_CONTRACT: TaskLoggerModel ->
# {
# required_fields: {task_id: str, add_log_fn: Callable},
# optional_fields: {source: str},
# invariants: [
# "All specific log methods (info, error) delegate to _log",
# "with_source creates a new logger with the same task_id"
# ]
# }
# @TEST_FIXTURE: valid_task_logger -> {"task_id": "test_123", "add_log_fn": lambda *args: None, "source": "test_plugin"}
# @TEST_EDGE: missing_task_id -> raises TypeError
# @TEST_EDGE: invalid_add_log_fn -> raises TypeError
# @TEST_INVARIANT: consistent_delegation -> verifies: [valid_task_logger]
class TaskLogger:
"""
A dedicated logger for tasks that automatically tags logs with source attribution.