test contracts
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user