Skip to content

Commit 5ebf8fa

Browse files
committed
Update test_advisory.py
1 parent afe9b28 commit 5ebf8fa

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

vulnerabilities/tests/pipes/test_advisory.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,91 @@ def test_get_or_create_advisory_commit(advisory_commit):
257257
assert isinstance(commit, PackageCommitPatch)
258258
assert commit.commit_hash in [c.commit_hash for c in advisory_commit]
259259
assert commit.vcs_url in [c.vcs_url for c in advisory_commit]
260+
261+
262+
@pytest.mark.django_db
263+
def test_insert_advisory_v2_handles_multiple_objects_returned():
264+
"""
265+
Test that insert_advisory_v2 correctly handles AdvisoryV2.MultipleObjectsReturned
266+
exception when duplicate advisory records exist.
267+
268+
This test verifies the fix for issue #2081 where the exception handler was
269+
incorrectly catching Advisory.MultipleObjectsReturned instead of
270+
AdvisoryV2.MultipleObjectsReturned.
271+
"""
272+
from unittest.mock import MagicMock
273+
from django.db import connection
274+
from vulnerabilities.models import AdvisoryV2
275+
from vulnerabilities.pipes.advisory import insert_advisory_v2
276+
from vulnerabilities.utils import compute_content_id
277+
278+
# Create advisory data
279+
advisory_data = AdvisoryData(
280+
summary="Test advisory for exception handling",
281+
affected_packages=[
282+
AffectedPackage(
283+
package=PackageURL(type="pypi", name="test-package"),
284+
affected_version_range=VersionRange.from_string("vers:pypi/>=1.0.0|<=2.0.0"),
285+
)
286+
],
287+
references=[Reference(url="https://example.com/advisory/test")],
288+
date_published=timezone.now(),
289+
url="https://test-advisory.example.com/duplicated",
290+
advisory_id="TEST-2024-001",
291+
)
292+
293+
content_id = compute_content_id(advisory_data=advisory_data)
294+
295+
# Create the first advisory normally
296+
advisory1 = AdvisoryV2.objects.create(
297+
unique_content_id=content_id,
298+
url=advisory_data.url,
299+
datasource_id="test_pipeline",
300+
advisory_id=advisory_data.advisory_id,
301+
avid=f"test_pipeline/{advisory_data.advisory_id}",
302+
summary=advisory_data.summary,
303+
date_collected=timezone.now(),
304+
)
305+
306+
# Force create a duplicate by bypassing the unique constraint at the model level
307+
# This simulates a database inconsistency that could trigger MultipleObjectsReturned
308+
with connection.cursor() as cursor:
309+
# Temporarily disable the unique constraint to create a duplicate
310+
cursor.execute(
311+
"""
312+
INSERT INTO vulnerabilities_advisoryv2
313+
(unique_content_id, url, datasource_id, advisory_id, avid, summary, date_collected, status)
314+
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
315+
""",
316+
[
317+
content_id,
318+
advisory_data.url,
319+
"test_pipeline",
320+
advisory_data.advisory_id,
321+
f"test_pipeline/{advisory_data.advisory_id}",
322+
advisory_data.summary,
323+
timezone.now(),
324+
1, # AdvisoryStatusType.PUBLISHED
325+
]
326+
)
327+
328+
# Verify we have duplicates
329+
assert AdvisoryV2.objects.filter(unique_content_id=content_id, url=advisory_data.url).count() == 2
330+
331+
# Create a mock logger to verify error logging
332+
mock_logger = MagicMock()
333+
334+
# Now calling insert_advisory_v2 should raise AdvisoryV2.MultipleObjectsReturned
335+
with pytest.raises(AdvisoryV2.MultipleObjectsReturned):
336+
insert_advisory_v2(
337+
advisory=advisory_data,
338+
pipeline_id="test_pipeline",
339+
logger=mock_logger,
340+
)
341+
342+
# Verify that the error was logged
343+
mock_logger.error.assert_called_once()
344+
error_message = mock_logger.error.call_args[0][0]
345+
assert "Multiple Advisories returned" in error_message
346+
assert content_id in error_message
347+
assert advisory_data.url in error_message

0 commit comments

Comments
 (0)