Skip to content

Commit bce9801

Browse files
committed
add unit test
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent 458d945 commit bce9801

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# DejaCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: AGPL-3.0-only
5+
# See https://github.com/aboutcode-org/dejacode for support or download.
6+
# See https://aboutcode.org for more information about AboutCode FOSS projects.
7+
#
8+
9+
import io
10+
from unittest import TestCase
11+
from unittest.mock import MagicMock
12+
from unittest.mock import patch
13+
14+
import urllib3.connectionpool
15+
from requests.adapters import HTTPAdapter
16+
from urllib3.response import HTTPResponse
17+
from urllib3.util.retry import Retry
18+
19+
from dejacode_toolkit.vulnerablecode import VulnerableCode
20+
21+
22+
def make_dataspace(vulnerablecode_url="https://public.vulnerablecode.io"):
23+
config = MagicMock()
24+
config.vulnerablecode_url = vulnerablecode_url
25+
dataspace = MagicMock()
26+
dataspace.get_configuration.return_value = config
27+
return dataspace
28+
29+
30+
def make_urllib3_response(status, body=b"", headers=None):
31+
return HTTPResponse(
32+
body=io.BytesIO(body),
33+
headers=headers or {},
34+
status=status,
35+
preload_content=False,
36+
)
37+
38+
39+
class VulnerableCodenTestCase(TestCase):
40+
def setUp(self):
41+
self.service = VulnerableCode(make_dataspace())
42+
43+
def test_get_session_retry_configuration(self):
44+
session = self.service.get_session()
45+
adapter = session.get_adapter("https://example.com")
46+
47+
self.assertIsInstance(adapter, HTTPAdapter)
48+
self.assertIsInstance(adapter.max_retries, Retry)
49+
self.assertEqual(adapter.max_retries.total, 3)
50+
self.assertIn(429, adapter.max_retries.status_forcelist)
51+
self.assertIn("POST", adapter.max_retries.allowed_methods)
52+
self.assertTrue(adapter.max_retries.respect_retry_after_header)
53+
54+
@patch.object(urllib3.connectionpool.HTTPSConnectionPool, "_get_conn")
55+
@patch.object(urllib3.connectionpool.HTTPSConnectionPool, "_make_request")
56+
def test_bulk_search_by_purl_retries_on_429(self, mock_make_request, mock_get_conn):
57+
# _get_conn is mocked to prevent any real TCP connection attempt.
58+
mock_get_conn.return_value = MagicMock()
59+
60+
# _make_request is called once per attempt inside urllib3's retry loop,
61+
# so two side_effect values simulate: 429 on first try, 200 on retry.
62+
mock_make_request.side_effect = [
63+
make_urllib3_response(
64+
429,
65+
headers={"Retry-After": "0"},
66+
),
67+
make_urllib3_response(
68+
200,
69+
body=b'{"count": 1, "results": [{"purl": "pkg:pypi/django@4.2"}]}',
70+
headers={"Content-Type": "application/json"},
71+
),
72+
]
73+
74+
result = self.service.bulk_search_by_purl(purls=["pkg:pypi/django@4.2"])
75+
76+
self.assertEqual(mock_make_request.call_count, 2)
77+
self.assertIsNotNone(result)
78+
self.assertEqual(result["count"], 1)

0 commit comments

Comments
 (0)