|
|
|
@ -23,7 +23,7 @@ from cereal import messaging |
|
|
|
|
from openpilot.common.params import Params |
|
|
|
|
from openpilot.common.timeout import Timeout |
|
|
|
|
from openpilot.selfdrive.athena import athenad |
|
|
|
|
from openpilot.selfdrive.athena.athenad import MAX_RETRY_COUNT, dispatcher |
|
|
|
|
from openpilot.selfdrive.athena.athenad import MAX_RETRY_COUNT, cb, dispatcher |
|
|
|
|
from openpilot.selfdrive.athena.tests.helpers import MockWebsocket, MockApi, EchoSocket, with_http_server |
|
|
|
|
from openpilot.system.hardware.hw import Paths |
|
|
|
|
from openpilot.selfdrive.athena.tests.helpers import HTTPRequestHandler |
|
|
|
@ -49,7 +49,7 @@ def with_upload_handler(func): |
|
|
|
|
thread = threading.Thread(target=athenad.upload_handler, args=(end_event,)) |
|
|
|
|
thread.start() |
|
|
|
|
try: |
|
|
|
|
return func(*args, **kwargs) |
|
|
|
|
return func(*args, thread, end_event, **kwargs) |
|
|
|
|
finally: |
|
|
|
|
end_event.set() |
|
|
|
|
thread.join() |
|
|
|
@ -93,7 +93,10 @@ class TestAthenadMethods(unittest.TestCase): |
|
|
|
|
def _wait_for_upload(): |
|
|
|
|
now = time.time() |
|
|
|
|
while time.time() - now < 5: |
|
|
|
|
if athenad.upload_queue.qsize() == 0: |
|
|
|
|
print('we are here', time.time() - now, athenad.upload_queue.qsize(), athenad.cur_upload_items) |
|
|
|
|
time.sleep(0.1) |
|
|
|
|
if athenad.upload_queue.qsize() == 0 and list(athenad.cur_upload_items.values())[0] is None: |
|
|
|
|
print('BREAKING') |
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
@ -224,56 +227,91 @@ class TestAthenadMethods(unittest.TestCase): |
|
|
|
|
|
|
|
|
|
@with_mock_athena |
|
|
|
|
@with_upload_handler |
|
|
|
|
def test_upload_handler(self, host): |
|
|
|
|
fn = self._create_file('qlog.bz2') |
|
|
|
|
item = athenad.UploadItem(path=fn, url=f"{host}/qlog.bz2", headers={}, created_at=int(time.time()*1000), id='', allow_cellular=True) |
|
|
|
|
# @mock.patch('openpilot.selfdrive.athena.athenad.cb', new_callable=lambda: mock.MagicMock(wraps=athenad.cb)) |
|
|
|
|
@mock.patch('openpilot.selfdrive.athena.athenad.cb', autospec=True) |
|
|
|
|
def test_upload_handler(self, host, thread, end_event, mock_cb): |
|
|
|
|
print((host, end_event, mock_cb)) |
|
|
|
|
tid = list(athenad.cur_upload_items)[0] |
|
|
|
|
print(tid) |
|
|
|
|
print('START WITH_UPLOAD_HANDLER TEST') |
|
|
|
|
|
|
|
|
|
slept = False |
|
|
|
|
|
|
|
|
|
def monitor_cb(*args, **kwargs): |
|
|
|
|
nonlocal slept |
|
|
|
|
print('monitor_cb', athenad.cur_upload_items) |
|
|
|
|
_item = athenad.cur_upload_items[tid] |
|
|
|
|
print('PROGRESS!', _item.progress) |
|
|
|
|
if _item.progress > 0.2 and not slept: |
|
|
|
|
print('SLEEPING 5s!') |
|
|
|
|
end_event.set() |
|
|
|
|
time.sleep(1) |
|
|
|
|
slept = True |
|
|
|
|
cb(*args, **kwargs) |
|
|
|
|
|
|
|
|
|
athenad.upload_queue.put_nowait(item) |
|
|
|
|
self._wait_for_upload() |
|
|
|
|
time.sleep(0.1) |
|
|
|
|
mock_cb.side_effect = monitor_cb |
|
|
|
|
|
|
|
|
|
# TODO: verify that upload actually succeeded |
|
|
|
|
self.assertEqual(athenad.upload_queue.qsize(), 0) |
|
|
|
|
|
|
|
|
|
@parameterized.expand([(500, True), (412, False)]) |
|
|
|
|
@with_mock_athena |
|
|
|
|
@mock.patch('requests.put') |
|
|
|
|
@with_upload_handler |
|
|
|
|
def test_upload_handler_retry(self, status, retry, mock_put, host): |
|
|
|
|
mock_put.return_value.status_code = status |
|
|
|
|
fn = self._create_file('qlog.bz2') |
|
|
|
|
fn = self._create_file('qlog.bz2', data=os.urandom(2 * 1024 * 1024)) |
|
|
|
|
# item = athenad.UploadItem(path=fn, url=f"{host}/qlog.bz2", headers={'X-Delay-Upload': 'true'}, created_at=int(time.time()*1000), id='', allow_cellular=True) |
|
|
|
|
item = athenad.UploadItem(path=fn, url=f"{host}/qlog.bz2", headers={}, created_at=int(time.time()*1000), id='', allow_cellular=True) |
|
|
|
|
# print(item) |
|
|
|
|
|
|
|
|
|
athenad.upload_queue.put_nowait(item) |
|
|
|
|
self._wait_for_upload() |
|
|
|
|
time.sleep(0.1) |
|
|
|
|
|
|
|
|
|
self.assertEqual(athenad.upload_queue.qsize(), 1 if retry else 0) |
|
|
|
|
|
|
|
|
|
if retry: |
|
|
|
|
self.assertEqual(athenad.upload_queue.get().retry_count, 1) |
|
|
|
|
|
|
|
|
|
@with_upload_handler |
|
|
|
|
def test_upload_handler_timeout(self): |
|
|
|
|
"""When an upload times out or fails to connect it should be placed back in the queue""" |
|
|
|
|
fn = self._create_file('qlog.bz2') |
|
|
|
|
item = athenad.UploadItem(path=fn, url="http://localhost:44444/qlog.bz2", headers={}, created_at=int(time.time()*1000), id='', allow_cellular=True) |
|
|
|
|
item_no_retry = replace(item, retry_count=MAX_RETRY_COUNT) |
|
|
|
|
|
|
|
|
|
athenad.upload_queue.put_nowait(item_no_retry) |
|
|
|
|
self._wait_for_upload() |
|
|
|
|
time.sleep(0.1) |
|
|
|
|
|
|
|
|
|
# Check that upload with retry count exceeded is not put back |
|
|
|
|
self.assertEqual(athenad.upload_queue.qsize(), 0) |
|
|
|
|
|
|
|
|
|
athenad.upload_queue.put_nowait(item) |
|
|
|
|
# while 1: |
|
|
|
|
# time.sleep(0.01) |
|
|
|
|
# print(athenad.upload_queue.qsize(), athenad.cur_upload_items) |
|
|
|
|
# print() |
|
|
|
|
self._wait_for_upload() |
|
|
|
|
time.sleep(0.1) |
|
|
|
|
time.sleep(2) |
|
|
|
|
print('call count', mock_cb.call_count, len(athenad.cur_upload_items)) |
|
|
|
|
print('is alive', thread.is_alive(), athenad.cur_upload_items) |
|
|
|
|
self.assertEqual(athenad.cur_upload_items[tid].progress < 0.6) |
|
|
|
|
|
|
|
|
|
# Check that upload item was put back in the queue with incremented retry count |
|
|
|
|
self.assertEqual(athenad.upload_queue.qsize(), 1) |
|
|
|
|
self.assertEqual(athenad.upload_queue.get().retry_count, 1) |
|
|
|
|
# TODO: verify that upload actually succeeded |
|
|
|
|
self.assertEqual(athenad.upload_queue.qsize(), 0) |
|
|
|
|
self.assertEqual(athenad.cur_upload_items[tid], None) |
|
|
|
|
|
|
|
|
|
# @parameterized.expand([(500, True), (412, False)]) |
|
|
|
|
# @with_mock_athena |
|
|
|
|
# @mock.patch('requests.put') |
|
|
|
|
# @with_upload_handler |
|
|
|
|
# def test_upload_handler_retry(self, status, retry, mock_put, host): |
|
|
|
|
# mock_put.return_value.status_code = status |
|
|
|
|
# fn = self._create_file('qlog.bz2') |
|
|
|
|
# item = athenad.UploadItem(path=fn, url=f"{host}/qlog.bz2", headers={}, created_at=int(time.time()*1000), id='', allow_cellular=True) |
|
|
|
|
# |
|
|
|
|
# athenad.upload_queue.put_nowait(item) |
|
|
|
|
# self._wait_for_upload() |
|
|
|
|
# time.sleep(0.1) |
|
|
|
|
# |
|
|
|
|
# self.assertEqual(athenad.upload_queue.qsize(), 1 if retry else 0) |
|
|
|
|
# |
|
|
|
|
# if retry: |
|
|
|
|
# self.assertEqual(athenad.upload_queue.get().retry_count, 1) |
|
|
|
|
|
|
|
|
|
# @with_upload_handler |
|
|
|
|
# def test_upload_handler_timeout(self): |
|
|
|
|
# """When an upload times out or fails to connect it should be placed back in the queue""" |
|
|
|
|
# fn = self._create_file('qlog.bz2') |
|
|
|
|
# item = athenad.UploadItem(path=fn, url="http://localhost:44444/qlog.bz2", headers={}, created_at=int(time.time()*1000), id='', allow_cellular=True) |
|
|
|
|
# item_no_retry = replace(item, retry_count=MAX_RETRY_COUNT) |
|
|
|
|
# |
|
|
|
|
# athenad.upload_queue.put_nowait(item_no_retry) |
|
|
|
|
# self._wait_for_upload() |
|
|
|
|
# time.sleep(0.1) |
|
|
|
|
# |
|
|
|
|
# # Check that upload with retry count exceeded is not put back |
|
|
|
|
# self.assertEqual(athenad.upload_queue.qsize(), 0) |
|
|
|
|
# |
|
|
|
|
# athenad.upload_queue.put_nowait(item) |
|
|
|
|
# self._wait_for_upload() |
|
|
|
|
# time.sleep(0.1) |
|
|
|
|
# |
|
|
|
|
# # Check that upload item was put back in the queue with incremented retry count |
|
|
|
|
# self.assertEqual(athenad.upload_queue.qsize(), 1) |
|
|
|
|
# self.assertEqual(athenad.upload_queue.get().retry_count, 1) |
|
|
|
|
|
|
|
|
|
@with_upload_handler |
|
|
|
|
def test_cancelUpload(self): |
|
|
|
|