Initial server source import
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
APP_DIR = ROOT / 'app'
|
||||
sys.path.insert(0, str(APP_DIR))
|
||||
|
||||
import scanner
|
||||
|
||||
|
||||
class ApiDeadlinePlumbingTests(unittest.TestCase):
|
||||
def test_deadline_is_consumed_internally_not_forwarded_to_requests(self):
|
||||
response = mock.Mock(status_code=200)
|
||||
with mock.patch.object(scanner.requests, 'request', return_value=response) as request:
|
||||
result = scanner.api_request(
|
||||
'GET', 'https://example.invalid', timeout=10,
|
||||
deadline=time.monotonic() + 1,
|
||||
)
|
||||
self.assertIs(result, response)
|
||||
self.assertNotIn('deadline', request.call_args.kwargs)
|
||||
self.assertGreater(request.call_args.kwargs['timeout'], 0)
|
||||
self.assertLessEqual(request.call_args.kwargs['timeout'], 1)
|
||||
|
||||
def test_expired_deadline_never_reaches_requests(self):
|
||||
with mock.patch.object(scanner.requests, 'request') as request:
|
||||
with self.assertRaisesRegex(scanner.ApiRequestError, 'deadline expired'):
|
||||
scanner.api_request('GET', 'https://example.invalid', deadline=time.monotonic() - 1)
|
||||
request.assert_not_called()
|
||||
|
||||
|
||||
def test_deadline_bounds_unset_timeouts(self):
|
||||
for timeout in (None, (None, 30), (2, None), (None, None)):
|
||||
with self.subTest(timeout=timeout):
|
||||
response = mock.Mock(status_code=200)
|
||||
with mock.patch.object(scanner.scan_config, 'api_proxy_enabled', False), \
|
||||
mock.patch.object(scanner.requests, 'request', return_value=response) as request:
|
||||
self.assertIs(scanner.api_request(
|
||||
'GET', 'https://example.invalid', timeout=timeout,
|
||||
deadline=time.monotonic() + 1,
|
||||
), response)
|
||||
effective = request.call_args.kwargs['timeout']
|
||||
for value in effective if isinstance(effective, tuple) else (effective,):
|
||||
self.assertGreater(value, 0)
|
||||
self.assertLessEqual(value, 1)
|
||||
|
||||
def test_response_after_deadline_is_closed_not_returned_or_retried(self):
|
||||
for stream in (False, True):
|
||||
for status in (200, 503):
|
||||
with self.subTest(stream=stream, status=status):
|
||||
clock = [0.0]
|
||||
response = mock.Mock(status_code=status)
|
||||
|
||||
def late_response(*args, **kwargs):
|
||||
clock[0] = 11.0
|
||||
return response
|
||||
|
||||
with mock.patch.object(scanner.time, 'monotonic', side_effect=lambda: clock[0]), \
|
||||
mock.patch.object(scanner.scan_config, 'api_proxy_enabled', False), \
|
||||
mock.patch.object(scanner.requests, 'request', side_effect=late_response) as request, \
|
||||
mock.patch.object(scanner, '_wait_or_raise_scan_slot_fatal') as wait:
|
||||
with self.assertRaisesRegex(scanner.ApiRequestError, 'deadline expired after response'):
|
||||
scanner.api_request(
|
||||
'GET', 'https://example.invalid', timeout=30,
|
||||
deadline=10, max_retries=3, stream=stream,
|
||||
)
|
||||
request.assert_called_once()
|
||||
response.close.assert_called_once()
|
||||
wait.assert_not_called()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user