fix: commit verified semantic repair changes

This commit is contained in:
2026-03-21 11:05:20 +03:00
parent 5cca35f8d5
commit 1ce61d9533
10 changed files with 2504 additions and 901 deletions

View File

@@ -1,9 +1,9 @@
# [DEF:backend.tests.core.test_mapping_service:Module]
# [DEF:TestMappingService:Module]
#
# @COMPLEXITY: 3
# @PURPOSE: Unit tests for the IdMappingService matching UUIDs to integer IDs.
# @LAYER: Domain
# @RELATION: VERIFIES -> backend.src.core.mapping_service
# @RELATION: VERIFIES ->[src.core.mapping_service.IdMappingService]
#
import pytest
from datetime import datetime, timezone
@@ -21,16 +21,18 @@ if backend_dir not in sys.path:
from src.models.mapping import Base, ResourceMapping, ResourceType
from src.core.mapping_service import IdMappingService
@pytest.fixture
def db_session():
# In-memory SQLite for testing
engine = create_engine('sqlite:///:memory:')
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
yield session
session.close()
class MockSupersetClient:
def __init__(self, resources):
self.resources = resources
@@ -38,16 +40,25 @@ class MockSupersetClient:
def get_all_resources(self, endpoint, since_dttm=None):
return self.resources.get(endpoint, [])
# [DEF:test_sync_environment_upserts_correctly:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_sync_environment_upserts_correctly(db_session):
service = IdMappingService(db_session)
mock_client = MockSupersetClient({
"chart": [
{"id": 42, "uuid": "123e4567-e89b-12d3-a456-426614174000", "slice_name": "Test Chart"}
]
})
mock_client = MockSupersetClient(
{
"chart": [
{
"id": 42,
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"slice_name": "Test Chart",
}
]
}
)
service.sync_environment("test-env", mock_client)
mapping = db_session.query(ResourceMapping).first()
assert mapping is not None
assert mapping.environment_id == "test-env"
@@ -56,6 +67,12 @@ def test_sync_environment_upserts_correctly(db_session):
assert mapping.remote_integer_id == "42"
assert mapping.resource_name == "Test Chart"
# [/DEF:test_sync_environment_upserts_correctly:Function]
# [DEF:test_get_remote_id_returns_integer:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_get_remote_id_returns_integer(db_session):
service = IdMappingService(db_session)
mapping = ResourceMapping(
@@ -64,7 +81,7 @@ def test_get_remote_id_returns_integer(db_session):
uuid="uuid-1",
remote_integer_id="99",
resource_name="Test DS",
last_synced_at=datetime.now(timezone.utc)
last_synced_at=datetime.now(timezone.utc),
)
db_session.add(mapping)
db_session.commit()
@@ -72,80 +89,126 @@ def test_get_remote_id_returns_integer(db_session):
result = service.get_remote_id("test-env", ResourceType.DATASET, "uuid-1")
assert result == 99
# [/DEF:test_get_remote_id_returns_integer:Function]
# [DEF:test_get_remote_ids_batch_returns_dict:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_get_remote_ids_batch_returns_dict(db_session):
service = IdMappingService(db_session)
m1 = ResourceMapping(
environment_id="test-env",
resource_type=ResourceType.DASHBOARD,
uuid="uuid-1",
remote_integer_id="11"
remote_integer_id="11",
)
m2 = ResourceMapping(
environment_id="test-env",
resource_type=ResourceType.DASHBOARD,
uuid="uuid-2",
remote_integer_id="22"
remote_integer_id="22",
)
db_session.add_all([m1, m2])
db_session.commit()
result = service.get_remote_ids_batch("test-env", ResourceType.DASHBOARD, ["uuid-1", "uuid-2", "uuid-missing"])
result = service.get_remote_ids_batch(
"test-env", ResourceType.DASHBOARD, ["uuid-1", "uuid-2", "uuid-missing"]
)
assert len(result) == 2
assert result["uuid-1"] == 11
assert result["uuid-2"] == 22
assert "uuid-missing" not in result
# [/DEF:test_get_remote_ids_batch_returns_dict:Function]
# [DEF:test_sync_environment_updates_existing_mapping:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_sync_environment_updates_existing_mapping(db_session):
"""Verify that sync_environment updates an existing mapping (upsert UPDATE path)."""
from src.models.mapping import ResourceMapping
# Pre-populate a mapping
existing = ResourceMapping(
environment_id="test-env",
resource_type=ResourceType.CHART,
uuid="123e4567-e89b-12d3-a456-426614174000",
remote_integer_id="10",
resource_name="Old Name"
resource_name="Old Name",
)
db_session.add(existing)
db_session.commit()
service = IdMappingService(db_session)
mock_client = MockSupersetClient({
"chart": [
{"id": 42, "uuid": "123e4567-e89b-12d3-a456-426614174000", "slice_name": "Updated Name"}
]
})
mock_client = MockSupersetClient(
{
"chart": [
{
"id": 42,
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"slice_name": "Updated Name",
}
]
}
)
service.sync_environment("test-env", mock_client)
mapping = db_session.query(ResourceMapping).filter_by(
uuid="123e4567-e89b-12d3-a456-426614174000"
).first()
mapping = (
db_session.query(ResourceMapping)
.filter_by(uuid="123e4567-e89b-12d3-a456-426614174000")
.first()
)
assert mapping.remote_integer_id == "42"
assert mapping.resource_name == "Updated Name"
# Should still be only one record (updated, not duplicated)
count = db_session.query(ResourceMapping).count()
assert count == 1
# [/DEF:test_sync_environment_updates_existing_mapping:Function]
# [DEF:test_sync_environment_skips_resources_without_uuid:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_sync_environment_skips_resources_without_uuid(db_session):
"""Resources missing uuid or having id=None should be silently skipped."""
service = IdMappingService(db_session)
mock_client = MockSupersetClient({
"chart": [
{"id": 42, "slice_name": "No UUID"}, # Missing 'uuid' -> skipped
{"id": None, "uuid": "valid-uuid", "slice_name": "ID is None"}, # id=None -> skipped
{"id": None, "uuid": None, "slice_name": "Both None"}, # both None -> skipped
]
})
mock_client = MockSupersetClient(
{
"chart": [
{"id": 42, "slice_name": "No UUID"}, # Missing 'uuid' -> skipped
{
"id": None,
"uuid": "valid-uuid",
"slice_name": "ID is None",
}, # id=None -> skipped
{
"id": None,
"uuid": None,
"slice_name": "Both None",
}, # both None -> skipped
]
}
)
service.sync_environment("test-env", mock_client)
count = db_session.query(ResourceMapping).count()
assert count == 0
# [/DEF:test_sync_environment_skips_resources_without_uuid:Function]
# [DEF:test_sync_environment_handles_api_error_gracefully:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_sync_environment_handles_api_error_gracefully(db_session):
"""If one resource type fails, others should still sync."""
class FailingClient:
def get_all_resources(self, endpoint, since_dttm=None):
if endpoint == "chart":
@@ -162,12 +225,24 @@ def test_sync_environment_handles_api_error_gracefully(db_session):
mapping = db_session.query(ResourceMapping).first()
assert mapping.resource_type == ResourceType.DATASET
# [/DEF:test_sync_environment_handles_api_error_gracefully:Function]
# [DEF:test_get_remote_id_returns_none_for_missing:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_get_remote_id_returns_none_for_missing(db_session):
"""get_remote_id should return None when no mapping exists."""
service = IdMappingService(db_session)
result = service.get_remote_id("test-env", ResourceType.CHART, "nonexistent-uuid")
assert result is None
# [/DEF:test_get_remote_id_returns_none_for_missing:Function]
# [DEF:test_get_remote_ids_batch_returns_empty_for_empty_input:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_get_remote_ids_batch_returns_empty_for_empty_input(db_session):
"""get_remote_ids_batch should return {} for an empty list of UUIDs."""
service = IdMappingService(db_session)
@@ -175,70 +250,90 @@ def test_get_remote_ids_batch_returns_empty_for_empty_input(db_session):
assert result == {}
# [/DEF:test_get_remote_ids_batch_returns_empty_for_empty_input:Function]
# [DEF:test_mapping_service_alignment_with_test_data:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_mapping_service_alignment_with_test_data(db_session):
"""**@TEST_DATA**: Verifies that the service aligns with the resource_mapping_record contract."""
# Contract: {'environment_id': 'prod-env-1', 'resource_type': 'chart', 'uuid': '123e4567-e89b-12d3-a456-426614174000', 'remote_integer_id': '42'}
contract_data = {
'environment_id': 'prod-env-1',
'resource_type': ResourceType.CHART,
'uuid': '123e4567-e89b-12d3-a456-426614174000',
'remote_integer_id': '42'
"environment_id": "prod-env-1",
"resource_type": ResourceType.CHART,
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"remote_integer_id": "42",
}
mapping = ResourceMapping(**contract_data)
db_session.add(mapping)
db_session.commit()
service = IdMappingService(db_session)
result = service.get_remote_id(
contract_data['environment_id'],
contract_data['resource_type'],
contract_data['uuid']
contract_data["environment_id"],
contract_data["resource_type"],
contract_data["uuid"],
)
assert result == 42
# [/DEF:test_mapping_service_alignment_with_test_data:Function]
# [DEF:test_sync_environment_requires_existing_env:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_sync_environment_requires_existing_env(db_session):
"""**@PRE**: Verify behavior when environment_id is invalid/missing in DB.
Note: The current implementation doesn't strictly check for environment existencia in the DB
Note: The current implementation doesn't strictly check for environment existencia in the DB
before polling, but it should handle it gracefully or follow the contract.
"""
service = IdMappingService(db_session)
mock_client = MockSupersetClient({"chart": []})
# Even if environment doesn't exist in a hypothetical 'environments' table,
# Even if environment doesn't exist in a hypothetical 'environments' table,
# the service should still complete or fail according to defined error handling.
# In GRACE-Poly, @PRE is a hard requirement. If we don't have an Env model check,
# we simulate the intent.
service.sync_environment("non-existent-env", mock_client)
# If no error raised, at least verify no mappings were created for other envs
assert db_session.query(ResourceMapping).count() == 0
# [/DEF:test_sync_environment_requires_existing_env:Function]
# [DEF:test_sync_environment_deletes_stale_mappings:Function]
# @RELATION: BINDS_TO ->[TestMappingService]
def test_sync_environment_deletes_stale_mappings(db_session):
"""Verify that mappings for resources deleted from the remote environment
are removed from the local DB on the next sync cycle."""
service = IdMappingService(db_session)
# First sync: 2 charts exist
client_v1 = MockSupersetClient({
"chart": [
{"id": 1, "uuid": "aaa", "slice_name": "Chart A"},
{"id": 2, "uuid": "bbb", "slice_name": "Chart B"},
]
})
client_v1 = MockSupersetClient(
{
"chart": [
{"id": 1, "uuid": "aaa", "slice_name": "Chart A"},
{"id": 2, "uuid": "bbb", "slice_name": "Chart B"},
]
}
)
service.sync_environment("env1", client_v1)
assert db_session.query(ResourceMapping).filter_by(environment_id="env1").count() == 2
assert (
db_session.query(ResourceMapping).filter_by(environment_id="env1").count() == 2
)
# Second sync: user deleted Chart B from superset
client_v2 = MockSupersetClient({
"chart": [
{"id": 1, "uuid": "aaa", "slice_name": "Chart A"},
]
})
client_v2 = MockSupersetClient(
{
"chart": [
{"id": 1, "uuid": "aaa", "slice_name": "Chart A"},
]
}
)
service.sync_environment("env1", client_v2)
remaining = db_session.query(ResourceMapping).filter_by(environment_id="env1").all()
@@ -246,4 +341,5 @@ def test_sync_environment_deletes_stale_mappings(db_session):
assert remaining[0].uuid == "aaa"
# [/DEF:backend.tests.core.test_mapping_service:Module]
# [/DEF:test_sync_environment_deletes_stale_mappings:Function]
# [/DEF:TestMappingService:Module]