Publish curated ITWorx-ModelForge source from 990401737f96c8d46a9f7b0d84994516cadcb6a0
This commit is contained in:
1 parent
7082ab955a
commit
848f0d8f8a
434 files changed
+67298
-4315
No files matched your search
@@ -0,0 +1,200 @@
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from sqlalchemy.dialects import sqlite
|
||||
|
||||
from modelforge_api.domain.model_changes import (
|
||||
ModelChangeCandidateLink,
|
||||
ModelChangeEvidenceLink,
|
||||
ModelChangeResponse,
|
||||
)
|
||||
from modelforge_api.persistence.models import (
|
||||
CapabilityDeployment,
|
||||
DiscoveryCandidateAssessment,
|
||||
SelectedModelComparison,
|
||||
)
|
||||
from modelforge_api.services.audit import AuditContext
|
||||
from modelforge_api.services.model_changes import ModelChangeError, ModelChangeService
|
||||
|
||||
|
||||
def _service() -> tuple[ModelChangeService, MagicMock]:
|
||||
session = MagicMock()
|
||||
service = ModelChangeService(session, AuditContext("operator", "test-user", "test-correlation"))
|
||||
return service, session
|
||||
|
||||
|
||||
def _open_case() -> SimpleNamespace:
|
||||
return SimpleNamespace(
|
||||
id=uuid4(),
|
||||
project_binding_id=uuid4(),
|
||||
current_deployment_id=uuid4(),
|
||||
candidate_model_id=None,
|
||||
candidate_revision_id=None,
|
||||
candidate_artifact_set_id=None,
|
||||
candidate_deployment_id=None,
|
||||
discovery_assessment_id=None,
|
||||
download_plan_id=None,
|
||||
artifact_job_id=None,
|
||||
selected_comparison_id=None,
|
||||
migration_plan_id=None,
|
||||
lifecycle_plan_id=None,
|
||||
status="searching",
|
||||
status_reason="",
|
||||
version=1,
|
||||
closed_at=None,
|
||||
updated_by="test-user",
|
||||
)
|
||||
|
||||
|
||||
def test_list_returns_a_bounded_filtered_page_with_stable_order(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
service, session = _service()
|
||||
binding_id = uuid4()
|
||||
row = SimpleNamespace(id=uuid4())
|
||||
session.scalar.return_value = 241
|
||||
session.scalars.return_value.all.return_value = [row]
|
||||
monkeypatch.setattr(
|
||||
service,
|
||||
"_response",
|
||||
lambda item: ModelChangeResponse.model_construct(id=item.id),
|
||||
)
|
||||
|
||||
page = service.list(
|
||||
project_key="examplerag",
|
||||
project_binding_id=binding_id,
|
||||
open_only=True,
|
||||
limit=100,
|
||||
offset=100,
|
||||
)
|
||||
|
||||
assert page.total == 241
|
||||
assert [item.id for item in page.items] == [row.id]
|
||||
statement = session.scalars.call_args.args[0]
|
||||
sql = str(statement.compile(dialect=sqlite.dialect()))
|
||||
assert "ORDER BY model_change_cases.updated_at DESC, model_change_cases.id ASC" in sql
|
||||
assert "LIMIT ? OFFSET ?" in sql
|
||||
assert statement._limit_clause.value == 100
|
||||
assert statement._offset_clause.value == 100
|
||||
count_sql = str(session.scalar.call_args.args[0].compile(dialect=sqlite.dialect()))
|
||||
assert "model_change_cases.closed_at IS NULL" in count_sql
|
||||
assert "model_change_cases.project_binding_id" in count_sql
|
||||
assert 'projects."key" =' in count_sql
|
||||
|
||||
|
||||
def _binding_context(row: SimpleNamespace) -> tuple[SimpleNamespace, SimpleNamespace, SimpleNamespace, SimpleNamespace]:
|
||||
binding = SimpleNamespace(id=row.project_binding_id)
|
||||
project = SimpleNamespace(id=uuid4(), key="examplerag", name="ExampleRAG")
|
||||
contract = SimpleNamespace(id=uuid4())
|
||||
capability = SimpleNamespace(id=uuid4(), key="rag.embedding")
|
||||
return binding, project, contract, capability
|
||||
|
||||
|
||||
def test_candidate_deployment_can_never_be_the_current_production_deployment(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
service, session = _service()
|
||||
row = _open_case()
|
||||
binding, project, contract, capability = _binding_context(row)
|
||||
deployment_id = row.current_deployment_id
|
||||
deployment = SimpleNamespace(
|
||||
id=deployment_id,
|
||||
capability_contract_id=contract.id,
|
||||
artifact_set_id=uuid4(),
|
||||
production=True,
|
||||
channel="stable",
|
||||
status="stable",
|
||||
deprecated_at=None,
|
||||
)
|
||||
monkeypatch.setattr(service, "_row", lambda _identifier, lock=False: row)
|
||||
monkeypatch.setattr(service, "_binding_context", lambda _binding_id: (binding, project, contract, capability))
|
||||
session.get.side_effect = lambda model, identifier: deployment if model is CapabilityDeployment and identifier == deployment_id else None
|
||||
|
||||
request = ModelChangeCandidateLink(expected_version=1, candidate_deployment_id=deployment_id)
|
||||
with pytest.raises(ModelChangeError) as exc:
|
||||
service.link_candidate(row.id, request)
|
||||
|
||||
assert exc.value.code == "MODEL_CHANGE_CANDIDATE_DEPLOYMENT_INVALID"
|
||||
session.commit.assert_not_called()
|
||||
|
||||
|
||||
def test_comparison_evidence_must_match_exact_project_and_current_candidate_pair(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
service, session = _service()
|
||||
row = _open_case()
|
||||
row.candidate_deployment_id = uuid4()
|
||||
binding, project, contract, capability = _binding_context(row)
|
||||
comparison_id = uuid4()
|
||||
comparison = SimpleNamespace(
|
||||
id=comparison_id,
|
||||
project_binding_id=uuid4(),
|
||||
current_deployment_id=row.current_deployment_id,
|
||||
candidate_deployment_id=row.candidate_deployment_id,
|
||||
status="completed",
|
||||
)
|
||||
monkeypatch.setattr(service, "_row", lambda _identifier, lock=False: row)
|
||||
monkeypatch.setattr(service, "_binding_context", lambda _binding_id: (binding, project, contract, capability))
|
||||
session.get.side_effect = lambda model, identifier: comparison if model is SelectedModelComparison and identifier == comparison_id else None
|
||||
|
||||
request = ModelChangeEvidenceLink(expected_version=1, selected_comparison_id=comparison_id)
|
||||
with pytest.raises(ModelChangeError) as exc:
|
||||
service.link_evidence(row.id, request)
|
||||
|
||||
assert exc.value.code == "MODEL_CHANGE_COMPARISON_MISMATCH"
|
||||
session.commit.assert_not_called()
|
||||
|
||||
|
||||
def test_discovery_assessment_must_belong_to_exact_immutable_revision(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
service, session = _service()
|
||||
row = _open_case()
|
||||
binding, project, contract, capability = _binding_context(row)
|
||||
model_id = uuid4()
|
||||
revision_id = uuid4()
|
||||
assessment_id = uuid4()
|
||||
revision = SimpleNamespace(id=revision_id, model_id=model_id, resolved_commit_sha="exact-sha")
|
||||
model = SimpleNamespace(id=model_id)
|
||||
assessment = SimpleNamespace(
|
||||
id=assessment_id,
|
||||
model_id=model_id,
|
||||
resolved_commit_sha="different-sha",
|
||||
)
|
||||
monkeypatch.setattr(service, "_row", lambda _identifier, lock=False: row)
|
||||
monkeypatch.setattr(service, "_binding_context", lambda _binding_id: (binding, project, contract, capability))
|
||||
|
||||
def get(model_type: object, identifier: object) -> object | None:
|
||||
from modelforge_api.persistence.models import Model, ModelRevision
|
||||
|
||||
if model_type is ModelRevision and identifier == revision_id:
|
||||
return revision
|
||||
if model_type is Model and identifier == model_id:
|
||||
return model
|
||||
if model_type is DiscoveryCandidateAssessment and identifier == assessment_id:
|
||||
return assessment
|
||||
return None
|
||||
|
||||
session.get.side_effect = get
|
||||
request = ModelChangeCandidateLink(
|
||||
expected_version=1,
|
||||
candidate_model_id=model_id,
|
||||
candidate_revision_id=revision_id,
|
||||
discovery_assessment_id=assessment_id,
|
||||
)
|
||||
|
||||
with pytest.raises(ModelChangeError) as exc:
|
||||
service.link_candidate(row.id, request)
|
||||
|
||||
assert exc.value.code == "MODEL_CHANGE_ASSESSMENT_MISMATCH"
|
||||
session.commit.assert_not_called()
|
||||
|
||||
|
||||
def test_stale_case_version_is_rejected_before_candidate_mutation(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
service, session = _service()
|
||||
row = _open_case()
|
||||
row.version = 7
|
||||
monkeypatch.setattr(service, "_row", lambda _identifier, lock=False: row)
|
||||
|
||||
request = ModelChangeCandidateLink(expected_version=6, candidate_model_id=uuid4())
|
||||
with pytest.raises(ModelChangeError) as exc:
|
||||
service.link_candidate(row.id, request)
|
||||
|
||||
assert exc.value.code == "MODEL_CHANGE_VERSION_CONFLICT"
|
||||
session.commit.assert_not_called()
|
||||
Reference in new issue
Block a user