Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
289 changes: 289 additions & 0 deletions upload/tests/views/test_combined_upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
from unittest.mock import patch

from django.conf import settings
from django.test import override_settings
from django.urls import reverse
from rest_framework.test import APIClient
from shared.django_apps.core.tests.factories import (
CommitFactory,
RepositoryFactory,
)

from reports.models import (
ReportSession,
RepositoryFlag,
UploadFlagMembership,
)
from services.archive import ArchiveService, MinioEndpoints
from upload.views.combined_upload import CanDoCoverageUploadsPermission


def test_get_repo(db):
repository = RepositoryFactory(
name="the_repo", author__username="codecov", author__service="github"
)
repository.save()
repo_slug = f"{repository.author.username}::::{repository.name}"
url = reverse(
"new_upload.combined_upload",
args=[repository.author.service, repo_slug],
)
client = APIClient()
client.credentials(HTTP_AUTHORIZATION="token " + repository.upload_token)
response = client.post(url, {}, format="json")
assert response.status_code == 400 # Bad request due to missing required fields
assert "commitid" in response.json()


@patch("services.task.TaskService.upload")
def test_get_repo_not_found(upload, db):
repository = RepositoryFactory(
name="the_repo", author__username="codecov", author__service="github"
)
repo_slug = "codecov::::wrong-repo-name"
url = reverse(
"new_upload.combined_upload",
args=[repository.author.service, repo_slug],
)
client = APIClient()
response = client.post(url, {}, format="json")
assert response.status_code == 401
assert response.json() == {"detail": "Not valid tokenless upload"}
assert not upload.called


def test_deactivated_repo(db):
repository = RepositoryFactory(
name="the_repo",
author__username="codecov",
author__service="github",
active=True,
activated=False,
)
repository.save()
repo_slug = f"{repository.author.username}::::{repository.name}"
url = reverse(
"new_upload.combined_upload",
args=[repository.author.service, repo_slug],
)
client = APIClient()
client.credentials(HTTP_AUTHORIZATION="token " + repository.upload_token)
response = client.post(url, {"commit_sha": "abc123"}, format="json")
assert response.status_code == 400
assert "This repository is deactivated" in str(response.json())


def test_combined_upload_with_errors(db):
repository = RepositoryFactory()
repo_slug = f"{repository.author.username}::::{repository.name}"
url = reverse(
"new_upload.combined_upload",
args=[repository.author.service, repo_slug],
)

client = APIClient()
client.credentials(HTTP_AUTHORIZATION="token " + repository.upload_token)

# Missing required fields
response = client.post(url, {}, format="json")
assert response.status_code == 400
assert "commitid" in response.json()

# Invalid flag format
response = client.post(
url, {"commit_sha": "abc123", "flags": "not-a-list"}, format="json"
)
assert response.status_code == 400
assert "flags" in response.json()


def test_combined_upload_post(db, mocker):
mocker.patch.object(
CanDoCoverageUploadsPermission, "has_permission", return_value=True
)
presigned_put_mock = mocker.patch(
"services.archive.StorageService.create_presigned_put",
return_value="presigned put",
)
upload_task_mock = mocker.patch(
"upload.views.uploads.trigger_upload_task", return_value=True
)

repository = RepositoryFactory(
name="the_repo1", author__username="codecov", author__service="github"
)
commit = CommitFactory(repository=repository)
repository.save()
commit.save()

owner = repository.author
client = APIClient()
client.force_authenticate(user=owner)
repo_slug = f"{repository.author.username}::::{repository.name}"
url = reverse(
"new_upload.combined_upload",
args=[repository.author.service, repo_slug],
)
response = client.post(
url,
{
"branch": "branch",
"ci_service": "ci_service",
"ci_url": "ci_url",
"code": "code",
"commit_sha": commit.commitid,
"flags": ["flag1", "flag2"],
"job_code": "job_code",
"version": "version",
},
format="json",
)
response_json = response.json()
upload = ReportSession.objects.filter(
report__commit=commit,
report__code="code",
upload_extras={"format_version": "v1"},
).first()
assert response.status_code == 201
assert all(
map(
lambda x: x in response_json.keys(),
["external_id", "created_at", "raw_upload_location", "url"],
)
)
assert (
response_json.get("url")
== f"{settings.CODECOV_DASHBOARD_URL}/{repository.author.service}/{repository.author.username}/{repository.name}/commit/{commit.commitid}"
)

assert ReportSession.objects.filter(
report__commit=commit,
report__code="code",
upload_extras={"format_version": "v1"},
).exists()
assert RepositoryFlag.objects.filter(
repository_id=repository.repoid, flag_name="flag1"
).exists()
assert RepositoryFlag.objects.filter(
repository_id=repository.repoid, flag_name="flag2"
).exists()
flag1 = RepositoryFlag.objects.filter(
repository_id=repository.repoid, flag_name="flag1"
).first()
flag2 = RepositoryFlag.objects.filter(
repository_id=repository.repoid, flag_name="flag2"
).first()
assert UploadFlagMembership.objects.filter(
report_session_id=upload.id, flag_id=flag1.id
).exists()
assert UploadFlagMembership.objects.filter(
report_session_id=upload.id, flag_id=flag2.id
).exists()
assert [flag for flag in upload.flags.all()] == [flag1, flag2]
Comment on lines +164 to +182
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of these exists calls, I would just assert that the flags are properly attached:

assert {flag.name for flag in upload.flags.all()} == {"flag1", "flag2"}

We shouldn’t care about the implementation details of how the database manages its relations and joins. We care that our upload has the proper flags.


archive_service = ArchiveService(repository)
assert upload.storage_path == MinioEndpoints.raw_with_upload_id.get_path(
version="v4",
date=upload.created_at.strftime("%Y-%m-%d"),
repo_hash=archive_service.storage_hash,
commit_sha=commit.commitid,
reportid=upload.report.external_id,
uploadid=upload.external_id,
)
presigned_put_mock.assert_called_with("archive", upload.storage_path, 10)
upload_task_mock.assert_called()


@override_settings(SHELTER_SHARED_SECRET="shelter-shared-secret")
def test_combined_upload_post_shelter(db, mocker):
mocker.patch.object(
CanDoCoverageUploadsPermission, "has_permission", return_value=True
)
presigned_put_mock = mocker.patch(
"services.archive.StorageService.create_presigned_put",
return_value="presigned put",
)
upload_task_mock = mocker.patch(
"upload.views.uploads.trigger_upload_task", return_value=True
)

repository = RepositoryFactory(
name="the_repo", author__username="codecov", author__service="github"
)
commit = CommitFactory(repository=repository)
repository.save()
commit.save()

owner = repository.author
client = APIClient()
client.force_authenticate(user=owner)
repo_slug = f"{repository.author.username}::::{repository.name}"
url = reverse(
"new_upload.combined_upload",
args=[repository.author.service, repo_slug],
)
response = client.post(
url,
{
"branch": "branch",
"ci_service": "ci_service",
"ci_url": "ci_url",
"code": "code",
"commit_sha": commit.commitid,
"flags": ["flag1", "flag2"],
"job_code": "job_code",
"storage_path": "shelter/test/path.txt",
"version": "version",
},
headers={
"X-Shelter-Token": "shelter-shared-secret",
"User-Agent": "codecov-cli/0.4.7",
},
format="json",
)
response_json = response.json()
upload = ReportSession.objects.filter(
report__commit=commit,
report__code="code",
upload_extras={"format_version": "v1"},
).first()
assert response.status_code == 201
assert all(
map(
lambda x: x in response_json.keys(),
["external_id", "created_at", "raw_upload_location", "url"],
)
)
assert (
response_json.get("url")
== f"{settings.CODECOV_DASHBOARD_URL}/{repository.author.service}/{repository.author.username}/{repository.name}/commit/{commit.commitid}"
)

assert ReportSession.objects.filter(
report__commit=commit,
report__code="code",
upload_extras={"format_version": "v1"},
).exists()
assert RepositoryFlag.objects.filter(
repository_id=repository.repoid, flag_name="flag1"
).exists()
assert RepositoryFlag.objects.filter(
repository_id=repository.repoid, flag_name="flag2"
).exists()
flag1 = RepositoryFlag.objects.filter(
repository_id=repository.repoid, flag_name="flag1"
).first()
flag2 = RepositoryFlag.objects.filter(
repository_id=repository.repoid, flag_name="flag2"
).first()
assert UploadFlagMembership.objects.filter(
report_session_id=upload.id, flag_id=flag1.id
).exists()
assert UploadFlagMembership.objects.filter(
report_session_id=upload.id, flag_id=flag2.id
).exists()
assert [flag for flag in upload.flags.all()] == [flag1, flag2]

assert upload.storage_path == "shelter/test/path.txt"
presigned_put_mock.assert_called_with("archive", upload.storage_path, 10)
upload_task_mock.assert_called()
32 changes: 15 additions & 17 deletions upload/tests/views/test_uploads.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@
)
from reports.tests.factories import CommitReportFactory, UploadFactory
from services.archive import ArchiveService, MinioEndpoints
from upload.views.uploads import CanDoCoverageUploadsPermission, UploadViews
from upload.views.uploads import (
CanDoCoverageUploadsPermission,
UploadViews,
activate_repo,
trigger_upload_task,
)


def test_upload_permission_class_pass(db, mocker):
Expand Down Expand Up @@ -197,7 +202,7 @@ def test_uploads_post(db, mocker, mock_redis):
return_value="presigned put",
)
upload_task_mock = mocker.patch(
"upload.views.uploads.UploadViews.trigger_upload_task", return_value=True
"upload.views.uploads.trigger_upload_task", return_value=True
)

repository = RepositoryFactory(
Expand Down Expand Up @@ -293,7 +298,7 @@ def test_uploads_post_tokenless(db, mocker, mock_redis, private, branch, branch_
return_value="presigned put",
)
upload_task_mock = mocker.patch(
"upload.views.uploads.UploadViews.trigger_upload_task", return_value=True
"upload.views.uploads.trigger_upload_task", return_value=True
)
analytics_service_mock = mocker.patch("upload.views.uploads.AnalyticsService")

Expand Down Expand Up @@ -433,7 +438,7 @@ def test_uploads_post_token_required_auth_check(
return_value="presigned put",
)
upload_task_mock = mocker.patch(
"upload.views.uploads.UploadViews.trigger_upload_task", return_value=True
"upload.views.uploads.trigger_upload_task", return_value=True
)
analytics_service_mock = mocker.patch("upload.views.uploads.AnalyticsService")

Expand Down Expand Up @@ -577,7 +582,7 @@ def test_uploads_post_github_oidc_auth(
return_value="presigned put",
)
upload_task_mock = mocker.patch(
"upload.views.uploads.UploadViews.trigger_upload_task", return_value=True
"upload.views.uploads.trigger_upload_task", return_value=True
)

repository = RepositoryFactory(
Expand Down Expand Up @@ -696,9 +701,7 @@ def test_uploads_post_shelter(db, mocker, mock_redis):
"services.archive.StorageService.create_presigned_put",
return_value="presigned put",
)
mocker.patch(
"upload.views.uploads.UploadViews.trigger_upload_task", return_value=True
)
mocker.patch("upload.views.uploads.trigger_upload_task", return_value=True)
mock_prometheus_metrics = mocker.patch("upload.metrics.API_UPLOAD_COUNTER.labels")

repository = RepositoryFactory(
Expand Down Expand Up @@ -798,14 +801,13 @@ def test_deactivated_repo(db, mocker, mock_redis):


def test_trigger_upload_task(db, mocker):
upload_views = UploadViews()
repo = RepositoryFactory.create()
upload = UploadFactory.create()
report = CommitReportFactory.create()
commitid = "commit id"
mocked_redis = mocker.patch("upload.views.uploads.get_redis_connection")
mocked_dispatched_task = mocker.patch("upload.views.uploads.dispatch_upload_task")
upload_views.trigger_upload_task(repo, commitid, upload, report)
trigger_upload_task(repo, commitid, upload, report)
mocked_redis.assert_called()
mocked_dispatched_task.assert_called()

Expand All @@ -814,8 +816,7 @@ def test_activate_repo(db):
repo = RepositoryFactory(
active=False, deleted=True, activated=False, coverage_enabled=False
)
upload_views = UploadViews()
upload_views.activate_repo(repo)
activate_repo(repo)
assert repo.active
assert repo.activated
assert not repo.deleted
Expand All @@ -826,8 +827,7 @@ def test_activate_already_activated_repo(db):
repo = RepositoryFactory(
active=True, activated=True, deleted=False, coverage_enabled=True
)
upload_views = UploadViews()
upload_views.activate_repo(repo)
activate_repo(repo)
assert repo.active


Expand Down Expand Up @@ -855,9 +855,7 @@ def test_uploads_post_github_enterprise_oidc_auth_jwks_url(
"services.archive.StorageService.create_presigned_put",
return_value="presigned put",
)
self.mocker.patch(
"upload.views.uploads.UploadViews.trigger_upload_task", return_value=True
)
self.mocker.patch("upload.views.uploads.trigger_upload_task", return_value=True)

repository = RepositoryFactory(
name="the_repo",
Expand Down
Loading
Loading