Files

119 lines
3.6 KiB
Python

from datetime import UTC, datetime
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from modelforge_api.persistence.models import Base, Model, ModelRevision
from modelforge_api.services.audit import AuditWriter
def test_m0_schema_contains_required_domain_tables() -> None:
required = {
"models",
"model_revisions",
"model_artifacts",
"derived_artifacts",
"runtime_profiles",
"deployments",
"capabilities",
"capability_contracts",
"projects",
"project_bindings",
"compute_nodes",
"accelerators",
"benchmark_suites",
"benchmark_runs",
"experiments",
"recommendations",
"promotions",
"migrations",
"audit_events",
"gpu_leases",
"resource_envelopes",
"host_telemetry_latest",
"accelerator_telemetry_latest",
"storage_volume_states",
"hardware_inventory_runs",
"node_enrollments",
"node_credentials",
"upstream_snapshots",
"upstream_files",
"artifact_sets",
"download_plans",
"download_plan_files",
"artifact_jobs",
"artifact_job_attempts",
"artifact_inspections",
"artifact_set_members",
}
assert required <= set(Base.metadata.tables)
def test_audit_events_cannot_be_updated_or_deleted() -> None:
engine = create_engine("sqlite+pysqlite:///:memory:")
Base.metadata.create_all(engine)
with Session(engine) as session:
event = AuditWriter(session, "operator", "test").write(
"test", "model", None, {}
)
session.commit()
event.outcome = "changed"
try:
raised = False
session.commit()
except ValueError:
raised = True
session.rollback()
assert raised
def test_approved_revision_identity_is_immutable() -> None:
engine = create_engine("sqlite+pysqlite:///:memory:")
Base.metadata.create_all(engine)
with Session(engine) as session:
model = Model(
key="test",
display_name="Test",
upstream_provider="test",
upstream_source="test/model",
modalities=[],
parameter_metadata={},
license_metadata={},
)
revision = ModelRevision(
model=model,
upstream_revision="main",
resolved_commit_sha="a" * 40,
metadata_snapshot={},
immutable_at=datetime.now(UTC),
)
session.add_all([model, revision])
session.commit()
revision.resolved_commit_sha = "b" * 40
with pytest.raises(ValueError, match="immutable approved fields"):
session.commit()
def test_accelerator_uuid_is_unique_per_node() -> None:
from sqlalchemy.exc import IntegrityError
from modelforge_api.persistence.models import Accelerator, ComputeNode
engine = create_engine("sqlite+pysqlite:///:memory:")
Base.metadata.create_all(engine)
with Session(engine) as session:
node = ComputeNode(key="node", hostname="host", display_name="Host", identity_source="test")
session.add(node)
session.flush()
session.add_all(
[
Accelerator(compute_node_id=node.id, device_index=0, device_uuid="GPU-A", name="A"),
Accelerator(
compute_node_id=node.id, device_index=1, device_uuid="GPU-A", name="A again"
),
]
)
with pytest.raises(IntegrityError):
session.commit()