Update tests for tag removal

- Remove Tag/TagHistory model tests from unit tests
- Update CacheSettings tests to remove allow_public_internet field
- Replace tag= with version= in upload_test_file calls
- Update test assertions to use versions instead of tags
- Remove tests for tag: prefix downloads (now uses version:)
- Update dependency tests for version-only schema
This commit is contained in:
Mondo Diaz
2026-02-03 12:45:44 -06:00
parent eb287edbda
commit cc5d67abd6
17 changed files with 247 additions and 486 deletions

View File

@@ -47,7 +47,7 @@ class TestUploadBasics:
expected_hash = compute_sha256(content)
result = upload_test_file(
integration_client, project_name, package_name, content, tag="v1"
integration_client, project_name, package_name, content, version="v1"
)
assert result["artifact_id"] == expected_hash
@@ -116,31 +116,23 @@ class TestUploadBasics:
assert result["created_at"] is not None
@pytest.mark.integration
def test_upload_without_tag_succeeds(self, integration_client, test_package):
"""Test upload without tag succeeds (no tag created)."""
def test_upload_without_version_succeeds(self, integration_client, test_package):
"""Test upload without version succeeds (no version created)."""
project, package = test_package
content = b"upload without tag test"
content = b"upload without version test"
expected_hash = compute_sha256(content)
files = {"file": ("no_tag.bin", io.BytesIO(content), "application/octet-stream")}
files = {"file": ("no_version.bin", io.BytesIO(content), "application/octet-stream")}
response = integration_client.post(
f"/api/v1/project/{project}/{package}/upload",
files=files,
# No tag parameter
# No version parameter
)
assert response.status_code == 200
result = response.json()
assert result["artifact_id"] == expected_hash
# Verify no tag was created - list tags and check
tags_response = integration_client.get(
f"/api/v1/project/{project}/{package}/tags"
)
assert tags_response.status_code == 200
tags = tags_response.json()
# Filter for tags pointing to this artifact
artifact_tags = [t for t in tags.get("items", tags) if t.get("artifact_id") == expected_hash]
assert len(artifact_tags) == 0, "Tag should not be created when not specified"
# Version should be None when not specified
assert result.get("version") is None
@pytest.mark.integration
def test_upload_creates_artifact_in_database(self, integration_client, test_package):
@@ -172,25 +164,29 @@ class TestUploadBasics:
assert s3_object_exists(expected_hash), "S3 object should exist after upload"
@pytest.mark.integration
def test_upload_with_tag_creates_tag_record(self, integration_client, test_package):
"""Test upload with tag creates tag record."""
def test_upload_with_version_creates_version_record(self, integration_client, test_package):
"""Test upload with version creates version record."""
project, package = test_package
content = b"tag creation test"
content = b"version creation test"
expected_hash = compute_sha256(content)
tag_name = "my-tag-v1"
version_name = "1.0.0"
upload_test_file(
integration_client, project, package, content, tag=tag_name
result = upload_test_file(
integration_client, project, package, content, version=version_name
)
# Verify tag exists
tags_response = integration_client.get(
f"/api/v1/project/{project}/{package}/tags"
# Verify version was created
assert result.get("version") == version_name
assert result["artifact_id"] == expected_hash
# Verify version exists in versions list
versions_response = integration_client.get(
f"/api/v1/project/{project}/{package}/versions"
)
assert tags_response.status_code == 200
tags = tags_response.json()
tag_names = [t["name"] for t in tags.get("items", tags)]
assert tag_name in tag_names
assert versions_response.status_code == 200
versions = versions_response.json()
version_names = [v["version"] for v in versions.get("items", [])]
assert version_name in version_names
class TestDuplicateUploads:
@@ -207,13 +203,13 @@ class TestDuplicateUploads:
# First upload
result1 = upload_test_file(
integration_client, project, package, content, tag="first"
integration_client, project, package, content, version="first"
)
assert result1["artifact_id"] == expected_hash
# Second upload
result2 = upload_test_file(
integration_client, project, package, content, tag="second"
integration_client, project, package, content, version="second"
)
assert result2["artifact_id"] == expected_hash
assert result1["artifact_id"] == result2["artifact_id"]
@@ -228,13 +224,13 @@ class TestDuplicateUploads:
# First upload
result1 = upload_test_file(
integration_client, project, package, content, tag="v1"
integration_client, project, package, content, version="v1"
)
assert result1["ref_count"] == 1
# Second upload
result2 = upload_test_file(
integration_client, project, package, content, tag="v2"
integration_client, project, package, content, version="v2"
)
assert result2["ref_count"] == 2
@@ -261,12 +257,12 @@ class TestDuplicateUploads:
)
# Upload to first package
result1 = upload_test_file(integration_client, project, pkg1, content, tag="v1")
result1 = upload_test_file(integration_client, project, pkg1, content, version="v1")
assert result1["artifact_id"] == expected_hash
assert result1["deduplicated"] is False
# Upload to second package
result2 = upload_test_file(integration_client, project, pkg2, content, tag="v1")
result2 = upload_test_file(integration_client, project, pkg2, content, version="v1")
assert result2["artifact_id"] == expected_hash
assert result2["deduplicated"] is True
@@ -307,17 +303,17 @@ class TestDownload:
"""Tests for download functionality."""
@pytest.mark.integration
def test_download_by_tag(self, integration_client, test_package):
"""Test downloading artifact by tag name."""
def test_download_by_version(self, integration_client, test_package):
"""Test downloading artifact by version."""
project, package = test_package
original_content = b"download by tag test"
original_content = b"download by version test"
upload_test_file(
integration_client, project, package, original_content, tag="download-tag"
integration_client, project, package, original_content, version="1.0.0"
)
response = integration_client.get(
f"/api/v1/project/{project}/{package}/+/download-tag",
f"/api/v1/project/{project}/{package}/+/1.0.0",
params={"mode": "proxy"},
)
assert response.status_code == 200
@@ -340,29 +336,29 @@ class TestDownload:
assert response.content == original_content
@pytest.mark.integration
def test_download_by_tag_prefix(self, integration_client, test_package):
"""Test downloading artifact using tag: prefix."""
def test_download_by_version_prefix(self, integration_client, test_package):
"""Test downloading artifact using version: prefix."""
project, package = test_package
original_content = b"download by tag prefix test"
original_content = b"download by version prefix test"
upload_test_file(
integration_client, project, package, original_content, tag="prefix-tag"
integration_client, project, package, original_content, version="2.0.0"
)
response = integration_client.get(
f"/api/v1/project/{project}/{package}/+/tag:prefix-tag",
f"/api/v1/project/{project}/{package}/+/version:2.0.0",
params={"mode": "proxy"},
)
assert response.status_code == 200
assert response.content == original_content
@pytest.mark.integration
def test_download_nonexistent_tag(self, integration_client, test_package):
"""Test downloading nonexistent tag returns 404."""
def test_download_nonexistent_version(self, integration_client, test_package):
"""Test downloading nonexistent version returns 404."""
project, package = test_package
response = integration_client.get(
f"/api/v1/project/{project}/{package}/+/nonexistent-tag"
f"/api/v1/project/{project}/{package}/+/nonexistent-version"
)
assert response.status_code == 404
@@ -400,7 +396,7 @@ class TestDownload:
original_content = b"exact content verification test data 12345"
upload_test_file(
integration_client, project, package, original_content, tag="verify"
integration_client, project, package, original_content, version="verify"
)
response = integration_client.get(
@@ -421,7 +417,7 @@ class TestDownloadHeaders:
upload_test_file(
integration_client, project, package, content,
filename="test.txt", tag="content-type-test"
filename="test.txt", version="content-type-test"
)
response = integration_client.get(
@@ -440,7 +436,7 @@ class TestDownloadHeaders:
expected_length = len(content)
upload_test_file(
integration_client, project, package, content, tag="content-length-test"
integration_client, project, package, content, version="content-length-test"
)
response = integration_client.get(
@@ -460,7 +456,7 @@ class TestDownloadHeaders:
upload_test_file(
integration_client, project, package, content,
filename=filename, tag="disposition-test"
filename=filename, version="disposition-test"
)
response = integration_client.get(
@@ -481,7 +477,7 @@ class TestDownloadHeaders:
expected_hash = compute_sha256(content)
upload_test_file(
integration_client, project, package, content, tag="checksum-headers"
integration_client, project, package, content, version="checksum-headers"
)
response = integration_client.get(
@@ -501,7 +497,7 @@ class TestDownloadHeaders:
expected_hash = compute_sha256(content)
upload_test_file(
integration_client, project, package, content, tag="etag-test"
integration_client, project, package, content, version="etag-test"
)
response = integration_client.get(
@@ -553,7 +549,7 @@ class TestConcurrentUploads:
response = client.post(
f"/api/v1/project/{project}/{package}/upload",
files=files,
data={"tag": f"concurrent-{tag_suffix}"},
data={"version": f"concurrent-{tag_suffix}"},
headers={"Authorization": f"Bearer {api_key}"},
)
if response.status_code == 200:
@@ -605,7 +601,7 @@ class TestFileSizeValidation:
content = b"X"
result = upload_test_file(
integration_client, project, package, content, tag="tiny"
integration_client, project, package, content, version="tiny"
)
assert result["artifact_id"] is not None
@@ -621,7 +617,7 @@ class TestFileSizeValidation:
expected_size = len(content)
result = upload_test_file(
integration_client, project, package, content, tag="size-test"
integration_client, project, package, content, version="size-test"
)
assert result["size"] == expected_size
@@ -649,7 +645,7 @@ class TestUploadFailureCleanup:
response = integration_client.post(
f"/api/v1/project/nonexistent-project-{unique_test_id}/nonexistent-pkg/upload",
files=files,
data={"tag": "test"},
data={"version": "test"},
)
assert response.status_code == 404
@@ -672,7 +668,7 @@ class TestUploadFailureCleanup:
response = integration_client.post(
f"/api/v1/project/{test_project}/nonexistent-package-{unique_test_id}/upload",
files=files,
data={"tag": "test"},
data={"version": "test"},
)
assert response.status_code == 404
@@ -693,7 +689,7 @@ class TestUploadFailureCleanup:
response = integration_client.post(
f"/api/v1/project/{test_project}/nonexistent-package-{unique_test_id}/upload",
files=files,
data={"tag": "test"},
data={"version": "test"},
)
assert response.status_code == 404
@@ -719,7 +715,7 @@ class TestS3StorageVerification:
# Upload same content multiple times
for tag in ["s3test1", "s3test2", "s3test3"]:
upload_test_file(integration_client, project, package, content, tag=tag)
upload_test_file(integration_client, project, package, content, version=tag)
# Verify only one S3 object exists
s3_objects = list_s3_objects_by_hash(expected_hash)
@@ -744,7 +740,7 @@ class TestS3StorageVerification:
# Upload same content multiple times
for tag in ["v1", "v2", "v3"]:
upload_test_file(integration_client, project, package, content, tag=tag)
upload_test_file(integration_client, project, package, content, version=tag)
# Query artifact
response = integration_client.get(f"/api/v1/artifact/{expected_hash}")
@@ -783,7 +779,7 @@ class TestSecurityPathTraversal:
response = integration_client.post(
f"/api/v1/project/{project}/{package}/upload",
files=files,
data={"tag": "traversal-test"},
data={"version": "traversal-test"},
)
assert response.status_code == 200
result = response.json()
@@ -801,48 +797,16 @@ class TestSecurityPathTraversal:
assert response.status_code in [400, 404, 422]
@pytest.mark.integration
def test_path_traversal_in_tag_name(self, integration_client, test_package):
"""Test tag names with path traversal are handled safely."""
def test_path_traversal_in_version_name(self, integration_client, test_package):
"""Test version names with path traversal are handled safely."""
project, package = test_package
content = b"tag traversal test"
content = b"version traversal test"
files = {"file": ("test.bin", io.BytesIO(content), "application/octet-stream")}
response = integration_client.post(
f"/api/v1/project/{project}/{package}/upload",
files=files,
data={"tag": "../../../etc/passwd"},
)
assert response.status_code in [200, 400, 422]
@pytest.mark.integration
def test_download_path_traversal_in_ref(self, integration_client, test_package):
"""Test download ref with path traversal is rejected."""
project, package = test_package
response = integration_client.get(
f"/api/v1/project/{project}/{package}/+/../../../etc/passwd"
)
assert response.status_code in [400, 404, 422]
@pytest.mark.integration
def test_path_traversal_in_package_name(self, integration_client, test_project):
"""Test package names with path traversal sequences are rejected."""
response = integration_client.get(
f"/api/v1/project/{test_project}/packages/../../../etc/passwd"
)
assert response.status_code in [400, 404, 422]
@pytest.mark.integration
def test_path_traversal_in_tag_name(self, integration_client, test_package):
"""Test tag names with path traversal are rejected or handled safely."""
project, package = test_package
content = b"tag traversal test"
files = {"file": ("test.bin", io.BytesIO(content), "application/octet-stream")}
response = integration_client.post(
f"/api/v1/project/{project}/{package}/upload",
files=files,
data={"tag": "../../../etc/passwd"},
data={"version": "../../../etc/passwd"},
)
assert response.status_code in [200, 400, 422]
@@ -867,7 +831,7 @@ class TestSecurityMalformedRequests:
response = integration_client.post(
f"/api/v1/project/{project}/{package}/upload",
data={"tag": "no-file"},
data={"version": "no-file"},
)
assert response.status_code == 422