"""Tests for database utility functions.""" import pytest from unittest.mock import MagicMock, patch class TestArtifactRepository: """Tests for ArtifactRepository.""" def test_batch_dependency_values_formatting(self): """batch_upsert_dependencies should format values correctly.""" from app.db_utils import ArtifactRepository deps = [ ("_pypi", "numpy", ">=1.21.0"), ("_pypi", "requests", "*"), ("myproject", "mylib", "==1.0.0"), ] values = ArtifactRepository._format_dependency_values("abc123", deps) assert len(values) == 3 assert values[0] == { "artifact_id": "abc123", "dependency_project": "_pypi", "dependency_package": "numpy", "version_constraint": ">=1.21.0", } assert values[2]["dependency_project"] == "myproject" def test_empty_dependencies_returns_empty_list(self): """Empty dependency list should return empty values.""" from app.db_utils import ArtifactRepository values = ArtifactRepository._format_dependency_values("abc123", []) assert values == [] def test_format_dependency_values_preserves_special_characters(self): """Version constraints with special characters should be preserved.""" from app.db_utils import ArtifactRepository deps = [ ("_pypi", "package-name", ">=1.0.0,<2.0.0"), ("_pypi", "another_pkg", "~=1.4.2"), ] values = ArtifactRepository._format_dependency_values("hash123", deps) assert values[0]["version_constraint"] == ">=1.0.0,<2.0.0" assert values[1]["version_constraint"] == "~=1.4.2" def test_batch_upsert_dependencies_returns_zero_for_empty(self): """batch_upsert_dependencies should return 0 for empty list without DB call.""" from app.db_utils import ArtifactRepository mock_db = MagicMock() repo = ArtifactRepository(mock_db) result = repo.batch_upsert_dependencies("abc123", []) assert result == 0 # Verify no DB operations were performed mock_db.execute.assert_not_called() def test_get_or_create_artifact_builds_correct_statement(self): """get_or_create_artifact should use ON CONFLICT DO UPDATE.""" from app.db_utils import ArtifactRepository from app.models import Artifact mock_db = MagicMock() mock_result = MagicMock() mock_artifact = MagicMock() mock_artifact.ref_count = 1 mock_result.scalar_one.return_value = mock_artifact mock_db.execute.return_value = mock_result repo = ArtifactRepository(mock_db) artifact, created = repo.get_or_create_artifact( sha256="abc123def456", size=1024, filename="test.whl", content_type="application/zip", ) assert mock_db.execute.called assert created is True assert artifact == mock_artifact def test_get_or_create_artifact_existing_not_created(self): """get_or_create_artifact should return created=False for existing artifact.""" from app.db_utils import ArtifactRepository mock_db = MagicMock() mock_result = MagicMock() mock_artifact = MagicMock() mock_artifact.ref_count = 5 # Existing artifact with ref_count > 1 mock_result.scalar_one.return_value = mock_artifact mock_db.execute.return_value = mock_result repo = ArtifactRepository(mock_db) artifact, created = repo.get_or_create_artifact( sha256="abc123def456", size=1024, filename="test.whl", ) assert created is False def test_get_cached_url_with_artifact_returns_tuple(self): """get_cached_url_with_artifact should return (CachedUrl, Artifact) tuple.""" from app.db_utils import ArtifactRepository mock_db = MagicMock() mock_cached_url = MagicMock() mock_artifact = MagicMock() mock_db.query.return_value.join.return_value.filter.return_value.first.return_value = ( mock_cached_url, mock_artifact, ) repo = ArtifactRepository(mock_db) result = repo.get_cached_url_with_artifact("url_hash_123") assert result == (mock_cached_url, mock_artifact) def test_get_cached_url_with_artifact_returns_none_when_not_found(self): """get_cached_url_with_artifact should return None when URL not cached.""" from app.db_utils import ArtifactRepository mock_db = MagicMock() mock_db.query.return_value.join.return_value.filter.return_value.first.return_value = None repo = ArtifactRepository(mock_db) result = repo.get_cached_url_with_artifact("nonexistent_hash") assert result is None def test_get_artifact_dependencies_returns_list(self): """get_artifact_dependencies should return list of dependencies.""" from app.db_utils import ArtifactRepository mock_db = MagicMock() mock_dep1 = MagicMock() mock_dep2 = MagicMock() mock_db.query.return_value.filter.return_value.all.return_value = [ mock_dep1, mock_dep2, ] repo = ArtifactRepository(mock_db) result = repo.get_artifact_dependencies("artifact_hash_123") assert len(result) == 2 assert result[0] == mock_dep1 assert result[1] == mock_dep2 def test_get_artifact_dependencies_returns_empty_list(self): """get_artifact_dependencies should return empty list when no dependencies.""" from app.db_utils import ArtifactRepository mock_db = MagicMock() mock_db.query.return_value.filter.return_value.all.return_value = [] repo = ArtifactRepository(mock_db) result = repo.get_artifact_dependencies("artifact_without_deps") assert result == []