Skip to content

Commit

Permalink
🤖 Add tests for TokenlessAzureHandler timestamp handling (#1069)
Browse files Browse the repository at this point in the history
Co-authored-by: sentry-autofix[bot] <157164994+sentry-autofix[bot]@users.noreply.github.com>
Co-authored-by: trent-codecov <trent@codecov.io>
  • Loading branch information
sentry-autofix[bot] and trent-codecov authored Dec 20, 2024
1 parent ad92471 commit f80d9d2
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 0 deletions.
90 changes: 90 additions & 0 deletions upload/tests/test_tokenless_azure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from datetime import datetime, timedelta
from unittest.mock import patch

import pytest
from rest_framework.exceptions import NotFound

from upload.tokenless.azure import TokenlessAzureHandler


@pytest.fixture
def upload_params():
return {
"job": "899861",
"project": "public",
"server_uri": "https://dev.azure.com/dnceng-public/",
"build": "20241219.14",
"commit": "0f6e31fec5876be932f9e52f739ce1a2e04f11e3",
}


def test_verify_handles_nanosecond_timestamp(upload_params):
"""
Test that the handler correctly processes timestamps with nanosecond precision
from the Azure DevOps API.
"""
handler = TokenlessAzureHandler(upload_params)

# Mock a response with nanosecond precision timestamp (7 digits after decimal)
current_time = datetime.now()
timestamp = current_time.strftime("%Y-%m-%dT%H:%M:%S.1234567Z")

mock_build_response = {
"status": "completed",
"finishTime": timestamp,
"buildNumber": "20241219.14",
"sourceVersion": "0f6e31fec5876be932f9e52f739ce1a2e04f11e3",
"repository": {"type": "GitHub"},
}

with patch.object(handler, "get_build", return_value=mock_build_response):
service = handler.verify()
assert service == "github"


def test_verify_handles_microsecond_timestamp(upload_params):
"""
Test that the handler still works correctly with regular microsecond precision
timestamps.
"""
handler = TokenlessAzureHandler(upload_params)

# Mock a response with microsecond precision (6 digits after decimal)
current_time = datetime.now()
timestamp = current_time.strftime("%Y-%m-%dT%H:%M:%S.123456Z")

mock_build_response = {
"status": "completed",
"finishTime": timestamp,
"buildNumber": "20241219.14",
"sourceVersion": "0f6e31fec5876be932f9e52f739ce1a2e04f11e3",
"repository": {"type": "GitHub"},
}

with patch.object(handler, "get_build", return_value=mock_build_response):
service = handler.verify()
assert service == "github"


def test_verify_rejects_old_timestamp(upload_params):
"""
Test that the handler correctly rejects timestamps older than 4 minutes,
even with nanosecond precision.
"""
handler = TokenlessAzureHandler(upload_params)

# Create a timestamp that's more than 4 minutes old
old_time = datetime.now() - timedelta(minutes=5)
timestamp = old_time.strftime("%Y-%m-%dT%H:%M:%S.1234567Z")

mock_build_response = {
"status": "completed",
"finishTime": timestamp,
"buildNumber": "20241219.14",
"sourceVersion": "0f6e31fec5876be932f9e52f739ce1a2e04f11e3",
"repository": {"type": "GitHub"},
}

with patch.object(handler, "get_build", return_value=mock_build_response):
with pytest.raises(NotFound, match="Azure build has already finished"):
handler.verify()
5 changes: 5 additions & 0 deletions upload/tokenless/azure.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ def verify(self):
# Build should have finished within the last 4 mins OR should have an 'inProgress' flag
if build["status"] == "completed":
finishTimestamp = build["finishTime"].replace("T", " ").replace("Z", "")
# Azure DevOps API returns nanosecond precision (7 digits), but Python only supports
# microsecond precision (6 digits). Truncate to 6 digits after decimal.
if "." in finishTimestamp:
base, fraction = finishTimestamp.rsplit(".", 1)
finishTimestamp = f"{base}.{fraction[:6]}"
buildFinishDateObj = datetime.strptime(
finishTimestamp, "%Y-%m-%d %H:%M:%S.%f"
)
Expand Down

0 comments on commit f80d9d2

Please sign in to comment.