Skip to content

Commit 54b5dad

Browse files
committed
Update tests
Signed-off-by: Tushar Goel <[email protected]>
1 parent 823081b commit 54b5dad

File tree

1 file changed

+100
-22
lines changed

1 file changed

+100
-22
lines changed

vulnerabilities/tests/test_api_v2.py

Lines changed: 100 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def setUp(self):
5454
url="https://example.com/ref2", reference_type="exploit", reference_id="REF-2"
5555
)
5656
self.reference2.vulnerabilities.add(self.vuln2)
57+
5758
self.user = ApiUser.objects.create_api_user(username="[email protected]")
5859
self.auth = f"Token {self.user.auth_token.key}"
5960
self.client = APIClient(enforce_csrf_checks=True)
@@ -62,13 +63,16 @@ def setUp(self):
6263
def test_list_vulnerabilities(self):
6364
"""
6465
Test listing vulnerabilities without filters.
65-
Should return a list of vulnerabilities with IDs and URLs.
66+
Should return a paginated response with vulnerabilities dictionary.
6667
"""
6768
url = reverse("vulnerability-v2-list")
6869
response = self.client.get(url, format="json")
6970
self.assertEqual(response.status_code, status.HTTP_200_OK)
71+
self.assertIn("results", response.data)
7072
self.assertIn("vulnerabilities", response.data["results"])
7173
self.assertEqual(len(response.data["results"]["vulnerabilities"]), 2)
74+
self.assertIn("VCID-1234", response.data["results"]["vulnerabilities"])
75+
self.assertIn("VCID-5678", response.data["results"]["vulnerabilities"])
7276
self.assertTrue("url" in response.data["results"]["vulnerabilities"]["VCID-1234"])
7377

7478
def test_retrieve_vulnerability_detail(self):
@@ -100,6 +104,8 @@ def test_filter_vulnerability_by_alias(self):
100104
url = reverse("vulnerability-v2-list")
101105
response = self.client.get(url, {"alias": "CVE-2021-5678"}, format="json")
102106
self.assertEqual(response.status_code, status.HTTP_200_OK)
107+
self.assertIn("results", response.data)
108+
self.assertIn("vulnerabilities", response.data["results"])
103109
self.assertEqual(
104110
response.data["results"]["vulnerabilities"]["VCID-5678"]["vulnerability_id"],
105111
"VCID-5678",
@@ -159,9 +165,13 @@ def test_list_vulnerabilities_pagination(self):
159165
response = self.client.get(url, format="json")
160166
self.assertEqual(response.status_code, status.HTTP_200_OK)
161167
self.assertIn("results", response.data)
168+
self.assertIn("vulnerabilities", response.data["results"])
162169
self.assertIn("next", response.data)
163170
self.assertIn("previous", response.data)
164-
self.assertEqual(len(response.data["results"]), 1) # Assuming default page size is 10
171+
# The 'vulnerabilities' dictionary should contain vulnerabilities up to the page limit
172+
self.assertEqual(
173+
len(response.data["results"]["vulnerabilities"]), 10
174+
) # Assuming default page size is 10
165175

166176

167177
class PackageV2ViewSetTest(APITestCase):
@@ -185,6 +195,7 @@ def setUp(self):
185195
# Associate packages with vulnerabilities
186196
self.package1.affected_by_vulnerabilities.add(self.vuln1)
187197
self.package2.fixing_vulnerabilities.add(self.vuln2)
198+
188199
self.user = ApiUser.objects.create_api_user(username="[email protected]")
189200
self.auth = f"Token {self.user.auth_token.key}"
190201
self.client = APIClient(enforce_csrf_checks=True)
@@ -193,13 +204,24 @@ def setUp(self):
193204
def test_list_packages(self):
194205
"""
195206
Test listing packages without filters.
196-
Should return a list of packages with their details.
207+
Should return a list of packages with their details and associated vulnerabilities.
197208
"""
198209
url = reverse("package-v2-list")
199210
response = self.client.get(url, format="json")
200211
self.assertEqual(response.status_code, status.HTTP_200_OK)
212+
self.assertIn("results", response.data)
201213
self.assertIn("packages", response.data["results"])
214+
self.assertIn("vulnerabilities", response.data["results"])
202215
self.assertEqual(len(response.data["results"]["packages"]), 2)
216+
# Verify that vulnerabilities are included
217+
self.assertIsInstance(response.data["results"]["vulnerabilities"], dict)
218+
package_vulns = set()
219+
for package in response.data["results"]["packages"]:
220+
package_vulns.update(package["affected_by_vulnerabilities"])
221+
package_vulns.update(package["fixing_vulnerabilities"])
222+
self.assertTrue(
223+
all(vuln_id in response.data["results"]["vulnerabilities"] for vuln_id in package_vulns)
224+
)
203225

204226
def test_filter_packages_by_purl(self):
205227
"""
@@ -264,9 +286,13 @@ def test_list_packages_pagination(self):
264286
response = self.client.get(url, format="json")
265287
self.assertEqual(response.status_code, status.HTTP_200_OK)
266288
self.assertIn("results", response.data)
289+
self.assertIn("packages", response.data["results"])
290+
self.assertIn("vulnerabilities", response.data["results"])
267291
self.assertIn("next", response.data)
268292
self.assertIn("previous", response.data)
269-
self.assertEqual(len(response.data["results"]), 1) # Assuming default page size is 10
293+
self.assertEqual(
294+
len(response.data["results"]["packages"]), 10
295+
) # Assuming default page size is 10
270296

271297
def test_invalid_vulnerability_filter(self):
272298
"""
@@ -309,16 +335,27 @@ def test_get_fixing_vulnerabilities(self):
309335
def test_bulk_lookup_with_valid_purls(self):
310336
"""
311337
Test bulk lookup with valid PURLs.
338+
Should return packages and their associated vulnerabilities.
312339
"""
313340
url = reverse("package-v2-bulk-lookup")
314341
data = {"purls": ["pkg:pypi/[email protected]", "pkg:npm/[email protected]"]}
315342
response = self.client.post(url, data, format="json")
316343
self.assertEqual(response.status_code, status.HTTP_200_OK)
317-
self.assertEqual(len(response.data), 2)
344+
self.assertIn("packages", response.data)
345+
self.assertIn("vulnerabilities", response.data)
346+
self.assertEqual(len(response.data["packages"]), 2)
318347
# Verify that the returned data matches the packages
319-
purls = [package["purl"] for package in response.data]
348+
purls = [package["purl"] for package in response.data["packages"]]
320349
self.assertIn("pkg:pypi/[email protected]", purls)
321350
self.assertIn("pkg:npm/[email protected]", purls)
351+
# Verify that vulnerabilities are included
352+
package_vulns = set()
353+
for package in response.data["packages"]:
354+
package_vulns.update(package["affected_by_vulnerabilities"])
355+
package_vulns.update(package["fixing_vulnerabilities"])
356+
self.assertTrue(
357+
all(vuln_id in response.data["vulnerabilities"] for vuln_id in package_vulns)
358+
)
322359

323360
def test_bulk_lookup_with_invalid_purls(self):
324361
"""
@@ -329,7 +366,8 @@ def test_bulk_lookup_with_invalid_purls(self):
329366
response = self.client.post(url, data, format="json")
330367
self.assertEqual(response.status_code, status.HTTP_200_OK)
331368
# Since the packages don't exist, the response should be empty
332-
self.assertEqual(len(response.data), 0)
369+
self.assertEqual(len(response.data["packages"]), 0)
370+
self.assertEqual(len(response.data["vulnerabilities"]), 0)
333371

334372
def test_bulk_lookup_with_empty_purls(self):
335373
"""
@@ -347,23 +385,37 @@ def test_bulk_lookup_with_empty_purls(self):
347385
def test_bulk_search_with_valid_purls(self):
348386
"""
349387
Test bulk search with valid PURLs.
388+
Should return packages and their associated vulnerabilities.
350389
"""
351390
url = reverse("package-v2-bulk-search")
352391
data = {"purls": ["pkg:pypi/[email protected]", "pkg:npm/[email protected]"]}
353392
response = self.client.post(url, data, format="json")
354393
self.assertEqual(response.status_code, status.HTTP_200_OK)
355-
self.assertEqual(len(response.data), 2)
356-
purls = [package["purl"] for package in response.data]
394+
self.assertIn("packages", response.data)
395+
self.assertIn("vulnerabilities", response.data)
396+
self.assertEqual(len(response.data["packages"]), 2)
397+
purls = [package["purl"] for package in response.data["packages"]]
357398
self.assertIn("pkg:pypi/[email protected]", purls)
358399
self.assertIn("pkg:npm/[email protected]", purls)
400+
# Verify that vulnerabilities are included
401+
package_vulns = set()
402+
for package in response.data["packages"]:
403+
package_vulns.update(package["affected_by_vulnerabilities"])
404+
package_vulns.update(package["fixing_vulnerabilities"])
405+
self.assertTrue(
406+
all(vuln_id in response.data["vulnerabilities"] for vuln_id in package_vulns)
407+
)
359408

360409
def test_bulk_search_with_purl_only_true(self):
361410
"""
362411
Test bulk search with purl_only set to True.
363412
Should return only the PURLs of vulnerable packages.
364413
"""
365414
url = reverse("package-v2-bulk-search")
366-
data = {"purls": ["pkg:pypi/[email protected]", "pkg:npm/[email protected]"], "purl_only": True}
415+
data = {
416+
"purls": ["pkg:pypi/[email protected]", "pkg:npm/[email protected]"],
417+
"purl_only": True,
418+
}
367419
response = self.client.post(url, data, format="json")
368420
self.assertEqual(response.status_code, status.HTTP_200_OK)
369421
# Since purl_only=True, response should be a list of PURLs
@@ -375,15 +427,29 @@ def test_bulk_search_with_purl_only_true(self):
375427
def test_bulk_search_with_plain_purl_true(self):
376428
"""
377429
Test bulk search with plain_purl set to True.
378-
"""
430+
Should return packages grouped by plain PURLs.
431+
"""
432+
# Create another package with the same name and version but different qualifiers
433+
Package.objects.create(
434+
name="django",
435+
version="3.2",
436+
type="pypi",
437+
qualifiers={"extension": "tar.gz"},
438+
)
439+
379440
url = reverse("package-v2-bulk-search")
380-
data = {"purls": ["pkg:pypi/[email protected]", "pkg:pypi/[email protected]"], "plain_purl": True}
441+
data = {
442+
"purls": ["pkg:pypi/[email protected]", "pkg:pypi/[email protected]?extension=tar.gz"],
443+
"plain_purl": True,
444+
}
381445
response = self.client.post(url, data, format="json")
382446
self.assertEqual(response.status_code, status.HTTP_200_OK)
383-
# Since plain_purl=True, packages with the same name and version are grouped
384-
self.assertEqual(len(response.data), 1)
385-
purls = [package["purl"] for package in response.data]
386-
self.assertIn("pkg:pypi/[email protected]", purls[0] or "pkg:pypi/[email protected]" in purls[0])
447+
self.assertIn("packages", response.data)
448+
self.assertIn("vulnerabilities", response.data)
449+
# Since plain_purl=True, packages with the same type, namespace, name, version are grouped
450+
self.assertEqual(len(response.data["packages"]), 1)
451+
purl = response.data["packages"][0]["purl"]
452+
self.assertTrue(purl.startswith("pkg:pypi/[email protected]"))
387453

388454
def test_bulk_search_with_purl_only_and_plain_purl_true(self):
389455
"""
@@ -407,12 +473,15 @@ def test_bulk_search_with_purl_only_and_plain_purl_true(self):
407473
def test_bulk_search_with_invalid_purls(self):
408474
"""
409475
Test bulk search with invalid PURLs.
476+
Should return an empty response.
410477
"""
411478
url = reverse("package-v2-bulk-search")
412479
data = {"purls": ["pkg:pypi/[email protected]", "pkg:npm/[email protected]"]}
413480
response = self.client.post(url, data, format="json")
414481
self.assertEqual(response.status_code, status.HTTP_200_OK)
415-
self.assertEqual(len(response.data), 0)
482+
# Since the packages don't exist, the response should be empty
483+
self.assertEqual(len(response.data["packages"]), 0)
484+
self.assertEqual(len(response.data["vulnerabilities"]), 0)
416485

417486
def test_bulk_search_with_empty_purls(self):
418487
"""
@@ -434,32 +503,39 @@ def test_all_vulnerable_packages(self):
434503
url = reverse("package-v2-all")
435504
response = self.client.get(url, format="json")
436505
self.assertEqual(response.status_code, status.HTTP_200_OK)
437-
# Since package1 and package3 are vulnerable, they should be returned
506+
# Since package1 is vulnerable, it should be returned
438507
expected_purls = ["pkg:pypi/[email protected]"]
439508
self.assertEqual(sorted(response.data), sorted(expected_purls))
440509

441510
def test_lookup_with_valid_purl(self):
442511
"""
443512
Test the 'lookup' endpoint with a valid PURL.
513+
Should return the package and its associated vulnerabilities.
444514
"""
445515
url = reverse("package-v2-lookup")
446516
data = {"purl": "pkg:pypi/[email protected]"}
447517
response = self.client.post(url, data, format="json")
448518
self.assertEqual(response.status_code, status.HTTP_200_OK)
449-
self.assertEqual(len(response.data), 1)
519+
self.assertEqual(1, len(response.data))
520+
self.assertIn("purl", response.data[0])
521+
self.assertIn("affected_by_vulnerabilities", response.data[0])
522+
self.assertIn("fixing_vulnerabilities", response.data[0])
523+
self.assertIn("next_non_vulnerable_version", response.data[0])
524+
self.assertIn("latest_non_vulnerable_version", response.data[0])
450525
self.assertEqual(response.data[0]["purl"], "pkg:pypi/[email protected]")
451526
self.assertEqual(response.data[0]["affected_by_vulnerabilities"], ["VCID-1234"])
527+
self.assertEqual(response.data[0]["fixing_vulnerabilities"], [])
452528

453529
def test_lookup_with_invalid_purl(self):
454530
"""
455531
Test the 'lookup' endpoint with a PURL that does not exist.
456-
Should return an empty list.
532+
Should return empty packages and vulnerabilities.
457533
"""
458534
url = reverse("package-v2-lookup")
459535
data = {"purl": "pkg:pypi/[email protected]"}
460536
response = self.client.post(url, data, format="json")
461537
self.assertEqual(response.status_code, status.HTTP_200_OK)
462-
# No packages should be returned
538+
# No packages or vulnerabilities should be returned
463539
self.assertEqual(len(response.data), 0)
464540

465541
def test_lookup_with_missing_purl(self):
@@ -478,9 +554,11 @@ def test_lookup_with_missing_purl(self):
478554
def test_lookup_with_invalid_purl_format(self):
479555
"""
480556
Test the 'lookup' endpoint with an invalid PURL format.
481-
Should return 400 Bad Request.
557+
Should return empty packages and vulnerabilities.
482558
"""
483559
url = reverse("package-v2-lookup")
484560
data = {"purl": "invalid_purl_format"}
485561
response = self.client.post(url, data, format="json")
486562
self.assertEqual(response.status_code, status.HTTP_200_OK)
563+
# No packages or vulnerabilities should be returned
564+
self.assertEqual(len(response.data), 0)

0 commit comments

Comments
 (0)