Files
StarPilot/openpilot/system/athena/tests/test_upload_preferences.py
T
firestar5683 6d742eb343 CI
Add control trace and platform qualification tools that exercise explicit safety modes and vehicle coverage.

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com>
Co-authored-by: Kacper Rączy <gfw.kra@gmail.com>
Co-authored-by: YassineYousfi <yyousfi1@binghamton.edu>
Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com>

Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>

Co-authored-by: prabhaavp <prabhaav@msu.edu>
2026-10-14 19:56:17 -05:00

78 lines
3.5 KiB
Python

"""Live metered-upload preferences in the actual Athena worker and callback."""
from contextlib import contextmanager
from datetime import datetime
from pathlib import Path
from types import SimpleNamespace
import queue
import tempfile
import threading
import unittest
from unittest.mock import Mock, patch
from openpilot.common.params import Params
from openpilot.system.athena import athenad
class UploadPreferencesTest(unittest.TestCase):
def setUp(self):
temporary = tempfile.TemporaryDirectory()
self.addCleanup(temporary.cleanup)
self.root = Path(temporary.name)
self.params = Params(str(self.root / 'params'))
self.file = self.root / 'rlog.zst'
self.file.write_bytes(b'log')
def master(self, metered):
data = SimpleNamespace(networkMetered=metered, networkType=SimpleNamespace(raw=4))
master = Mock()
master.__getitem__ = Mock(return_value=data)
master.recv_time = {'deviceState': 0.}
return master
def item(self, allow_cellular=False):
return athenad.UploadItem(path=str(self.file), url='https://unused.example/upload', headers={},
created_at=int(datetime.now().timestamp() * 1000), id='test', allow_cellular=allow_cellular)
def test_actual_worker_admits_global_override_and_retains_default_policy(self):
for metered, item_allowed, override, expected in ((True, False, False, False), (True, False, True, True),
(True, True, False, True), (False, False, False, True)):
with self.subTest(metered=metered, item_allowed=item_allowed, override=override):
self.params.put_bool('AlwaysAllowUploads', override, block=True)
end = threading.Event()
pending = queue.Queue()
pending.put(self.item(item_allowed))
transfer = Mock()
@contextmanager
def upload(item, callback, transfer=transfer, end=end):
transfer(item)
callback(3, 1)
yield SimpleNamespace(status_code=201)
end.set()
with patch.object(athenad, 'Params', return_value=self.params), \
patch.object(athenad.messaging, 'SubMaster', return_value=self.master(metered)), \
patch.object(athenad, 'upload_queue', pending), patch.object(athenad, 'cur_upload_items', {}), \
patch.object(athenad, 'cancelled_uploads', set()), patch.object(athenad, '_do_upload', side_effect=upload), \
patch.object(athenad.UploadQueueCache, 'cache'), \
patch.object(athenad, 'retry_upload', side_effect=lambda *args, stop=end: stop.set()) as retry:
athenad.upload_handler(end)
self.assertEqual(transfer.call_count, int(expected))
self.assertEqual(retry.call_count, int(not expected))
def test_callback_rechecks_live_override_and_still_aborts_shutdown(self):
master = self.master(True)
item, end = self.item(), threading.Event()
with patch.object(athenad, 'Params', return_value=self.params), patch.object(athenad, 'cur_upload_items', {}):
self.params.put_bool('AlwaysAllowUploads', True, block=True)
athenad.cb(master, item, 1, end, 10, 1)
self.assertEqual(athenad.cur_upload_items[1].progress, .1)
self.params.put_bool('AlwaysAllowUploads', False, block=True)
with self.assertRaises(athenad.AbortTransferException):
athenad.cb(master, item, 1, end, 10, 2)
self.params.put_bool('AlwaysAllowUploads', True, block=True)
end.set()
with self.assertRaises(athenad.AbortTransferException):
athenad.cb(master, item, 1, end, 10, 2)