Initial public ModelForge release
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user