272 lines
8.3 KiB
Python
272 lines
8.3 KiB
Python
"""
|
|
Unit tests for SQLAlchemy models.
|
|
|
|
Tests cover:
|
|
- Model instantiation and defaults
|
|
- Property aliases (sha256, format_metadata)
|
|
- Relationship definitions
|
|
- Constraint definitions
|
|
"""
|
|
|
|
import pytest
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
|
|
class TestArtifactModel:
|
|
"""Tests for the Artifact model."""
|
|
|
|
@pytest.mark.unit
|
|
def test_artifact_sha256_property(self):
|
|
"""Test sha256 property is an alias for id."""
|
|
from app.models import Artifact
|
|
|
|
artifact = Artifact(
|
|
id="a" * 64,
|
|
size=1024,
|
|
created_by="test-user",
|
|
s3_key="fruits/aa/aa/test",
|
|
)
|
|
|
|
assert artifact.sha256 == artifact.id
|
|
assert artifact.sha256 == "a" * 64
|
|
|
|
@pytest.mark.unit
|
|
def test_artifact_format_metadata_alias(self):
|
|
"""Test format_metadata is an alias for artifact_metadata."""
|
|
from app.models import Artifact
|
|
|
|
test_metadata = {"format": "tarball", "version": "1.0.0"}
|
|
artifact = Artifact(
|
|
id="b" * 64,
|
|
size=2048,
|
|
created_by="test-user",
|
|
s3_key="fruits/bb/bb/test",
|
|
artifact_metadata=test_metadata,
|
|
)
|
|
|
|
assert artifact.format_metadata == test_metadata
|
|
assert artifact.format_metadata == artifact.artifact_metadata
|
|
|
|
@pytest.mark.unit
|
|
def test_artifact_format_metadata_setter(self):
|
|
"""Test format_metadata setter updates artifact_metadata."""
|
|
from app.models import Artifact
|
|
|
|
artifact = Artifact(
|
|
id="c" * 64,
|
|
size=512,
|
|
created_by="test-user",
|
|
s3_key="fruits/cc/cc/test",
|
|
)
|
|
|
|
new_metadata = {"type": "rpm", "arch": "x86_64"}
|
|
artifact.format_metadata = new_metadata
|
|
|
|
assert artifact.artifact_metadata == new_metadata
|
|
assert artifact.format_metadata == new_metadata
|
|
|
|
@pytest.mark.unit
|
|
def test_artifact_default_ref_count(self):
|
|
"""Test artifact ref_count column has default value of 1."""
|
|
from app.models import Artifact
|
|
|
|
# Check the column definition has the right default
|
|
ref_count_col = Artifact.__table__.columns["ref_count"]
|
|
assert ref_count_col.default is not None
|
|
assert ref_count_col.default.arg == 1
|
|
|
|
@pytest.mark.unit
|
|
def test_artifact_default_metadata_is_dict(self):
|
|
"""Test artifact default metadata is an empty dict."""
|
|
from app.models import Artifact
|
|
|
|
artifact = Artifact(
|
|
id="e" * 64,
|
|
size=100,
|
|
created_by="test-user",
|
|
s3_key="fruits/ee/ee/test",
|
|
)
|
|
|
|
# Default might be None until saved, but the column default is dict
|
|
assert artifact.artifact_metadata is None or isinstance(
|
|
artifact.artifact_metadata, dict
|
|
)
|
|
|
|
|
|
class TestProjectModel:
|
|
"""Tests for the Project model."""
|
|
|
|
@pytest.mark.unit
|
|
def test_project_default_is_public(self):
|
|
"""Test project is_public column has default value of True."""
|
|
from app.models import Project
|
|
|
|
# Check the column definition has the right default
|
|
is_public_col = Project.__table__.columns["is_public"]
|
|
assert is_public_col.default is not None
|
|
assert is_public_col.default.arg is True
|
|
|
|
@pytest.mark.unit
|
|
def test_project_uuid_generation(self):
|
|
"""Test project generates UUID by default."""
|
|
from app.models import Project
|
|
|
|
project = Project(
|
|
name="uuid-test-project",
|
|
created_by="test-user",
|
|
)
|
|
|
|
# UUID should be set by default function
|
|
assert project.id is not None or hasattr(Project.id, "default")
|
|
|
|
|
|
class TestPackageModel:
|
|
"""Tests for the Package model."""
|
|
|
|
@pytest.mark.unit
|
|
def test_package_default_format(self):
|
|
"""Test package format column has default value of 'generic'."""
|
|
from app.models import Package
|
|
|
|
# Check the column definition has the right default
|
|
format_col = Package.__table__.columns["format"]
|
|
assert format_col.default is not None
|
|
assert format_col.default.arg == "generic"
|
|
|
|
@pytest.mark.unit
|
|
def test_package_default_platform(self):
|
|
"""Test package platform column has default value of 'any'."""
|
|
from app.models import Package
|
|
|
|
# Check the column definition has the right default
|
|
platform_col = Package.__table__.columns["platform"]
|
|
assert platform_col.default is not None
|
|
assert platform_col.default.arg == "any"
|
|
|
|
|
|
class TestTagModel:
|
|
"""Tests for the Tag model."""
|
|
|
|
@pytest.mark.unit
|
|
def test_tag_requires_package_id(self):
|
|
"""Test tag requires package_id."""
|
|
from app.models import Tag
|
|
|
|
tag = Tag(
|
|
name="v1.0.0",
|
|
package_id=uuid.uuid4(),
|
|
artifact_id="f" * 64,
|
|
created_by="test-user",
|
|
)
|
|
|
|
assert tag.package_id is not None
|
|
assert tag.artifact_id == "f" * 64
|
|
|
|
|
|
class TestTagHistoryModel:
|
|
"""Tests for the TagHistory model."""
|
|
|
|
@pytest.mark.unit
|
|
def test_tag_history_default_change_type(self):
|
|
"""Test tag history change_type column has default value of 'update'."""
|
|
from app.models import TagHistory
|
|
|
|
# Check the column definition has the right default
|
|
change_type_col = TagHistory.__table__.columns["change_type"]
|
|
assert change_type_col.default is not None
|
|
assert change_type_col.default.arg == "update"
|
|
|
|
@pytest.mark.unit
|
|
def test_tag_history_allows_null_old_artifact(self):
|
|
"""Test tag history allows null old_artifact_id (for create events)."""
|
|
from app.models import TagHistory
|
|
|
|
history = TagHistory(
|
|
tag_id=uuid.uuid4(),
|
|
old_artifact_id=None,
|
|
new_artifact_id="h" * 64,
|
|
change_type="create",
|
|
changed_by="test-user",
|
|
)
|
|
|
|
assert history.old_artifact_id is None
|
|
|
|
|
|
class TestUploadModel:
|
|
"""Tests for the Upload model."""
|
|
|
|
@pytest.mark.unit
|
|
def test_upload_default_deduplicated_is_false(self):
|
|
"""Test upload deduplicated column has default value of False."""
|
|
from app.models import Upload
|
|
|
|
# Check the column definition has the right default
|
|
deduplicated_col = Upload.__table__.columns["deduplicated"]
|
|
assert deduplicated_col.default is not None
|
|
assert deduplicated_col.default.arg is False
|
|
|
|
@pytest.mark.unit
|
|
def test_upload_default_checksum_verified_is_true(self):
|
|
"""Test upload checksum_verified column has default value of True."""
|
|
from app.models import Upload
|
|
|
|
# Check the column definition has the right default
|
|
checksum_verified_col = Upload.__table__.columns["checksum_verified"]
|
|
assert checksum_verified_col.default is not None
|
|
assert checksum_verified_col.default.arg is True
|
|
|
|
|
|
class TestAccessPermissionModel:
|
|
"""Tests for the AccessPermission model."""
|
|
|
|
@pytest.mark.unit
|
|
def test_access_permission_levels(self):
|
|
"""Test valid access permission levels."""
|
|
from app.models import AccessPermission
|
|
|
|
# This tests the check constraint values
|
|
valid_levels = ["read", "write", "admin"]
|
|
|
|
for level in valid_levels:
|
|
permission = AccessPermission(
|
|
project_id=uuid.uuid4(),
|
|
user_id="test-user",
|
|
level=level,
|
|
)
|
|
assert permission.level == level
|
|
|
|
|
|
class TestAuditLogModel:
|
|
"""Tests for the AuditLog model."""
|
|
|
|
@pytest.mark.unit
|
|
def test_audit_log_required_fields(self):
|
|
"""Test audit log has all required fields."""
|
|
from app.models import AuditLog
|
|
|
|
log = AuditLog(
|
|
action="project.create",
|
|
resource="/projects/test-project",
|
|
user_id="test-user",
|
|
)
|
|
|
|
assert log.action == "project.create"
|
|
assert log.resource == "/projects/test-project"
|
|
assert log.user_id == "test-user"
|
|
|
|
@pytest.mark.unit
|
|
def test_audit_log_optional_details(self):
|
|
"""Test audit log can have optional details JSON."""
|
|
from app.models import AuditLog
|
|
|
|
details = {"old_value": "v1", "new_value": "v2"}
|
|
log = AuditLog(
|
|
action="tag.update",
|
|
resource="/projects/test/packages/pkg/tags/latest",
|
|
user_id="test-user",
|
|
details=details,
|
|
)
|
|
|
|
assert log.details == details
|