Files
StarPilot/openpilot/starpilot/software/tests/test_update_process.py
T
firestar5683 80fbb4f6db Feature registration
Register vehicle controls, planner modes, UI actions and Galaxy services after their providers exist. Wire the shared runtime entrypoints and cover their combined behavior.

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
Co-authored-by: Daniel Koepping <elkoled@gmail.com>
Co-authored-by: Danny <dannyirwin31@yahoo.com>
Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com>
Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com>
Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com>
Co-authored-by: Kacper Rączy <gfw.kra@gmail.com>
Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu>
Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>
Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com>
Co-authored-by: stef <19478336+stefpi@users.noreply.github.com>
Co-authored-by: whoisdomi <dcantu83@gmail.com>

Co-authored-by: Intelli <contact@intelli.software>
Co-authored-by: haraschax <6804392+haraschax@users.noreply.github.com>
Co-authored-by: prabhaavp <prabhaav@msu.edu>
2026-10-14 20:02:39 -05:00

102 lines
3.1 KiB
Python

import os
from pathlib import Path
import subprocess
import sys
import tempfile
import time
import unittest
from openpilot.starpilot.software.fast_update import run
class TestUpdateProcess(unittest.TestCase):
def setUp(self):
self.temporary = tempfile.TemporaryDirectory()
self.addCleanup(self.temporary.cleanup)
self.directory = Path(self.temporary.name)
def command(self, source):
script = self.directory / 'command.py'
script.write_text(source)
return [sys.executable, '-u', str(script)]
def test_output_and_failure(self):
command = self.command("import sys\nprint('first')\nprint('last', file=sys.stderr)\nsys.exit(7)\n")
with self.assertRaises(subprocess.CalledProcessError) as error:
run(command, self.directory)
self.assertEqual(error.exception.returncode, 7)
self.assertEqual(error.exception.output, b'first\nlast\n')
def test_progress_and_success(self):
command = self.command("print('Receiving objects: 50%\\rReceiving objects: 100%')\nprint('done')\n")
progress = []
result = run(command, self.directory, progress.append)
self.assertEqual(result, 'Receiving objects: 50%\rReceiving objects: 100%\ndone\n')
self.assertEqual(progress, ['Receiving objects: 50%', 'Receiving objects: 100%'])
def test_timeout_allows_lock_cleanup(self):
command = self.command("""import signal
import time
from pathlib import Path
def terminate(*_):
raise SystemExit(1)
signal.signal(signal.SIGTERM, terminate)
lock = Path('shallow.lock')
lock.touch()
print('locked')
try:
time.sleep(60)
finally:
lock.unlink()
""")
with self.assertRaises(subprocess.TimeoutExpired) as error:
run(command, self.directory, timeout=0.5)
self.assertEqual(error.exception.output, b'locked\n')
self.assertFalse((self.directory / 'shallow.lock').exists())
def test_stubborn_command_is_killed(self):
command = self.command("""import os
import signal
import time
signal.signal(signal.SIGTERM, signal.SIG_IGN)
print(os.getpid())
time.sleep(60)
""")
started = time.monotonic()
with self.assertRaises(subprocess.TimeoutExpired) as error:
run(command, self.directory, timeout=0.5)
self.assertLess(time.monotonic() - started, 8)
with self.assertRaises(ProcessLookupError):
os.kill(int(error.exception.output.strip()), 0)
def test_exited_parent_with_child_pipe_is_bounded(self):
command = self.command("""import subprocess
import sys
import time
from pathlib import Path
subprocess.Popen([sys.executable, '-u', '-c', '''import signal
import time
from pathlib import Path
def terminate(*_):
Path('child_stopped').touch()
raise SystemExit(0)
signal.signal(signal.SIGTERM, terminate)
Path('child_ready').touch()
time.sleep(60)
'''])
while not Path('child_ready').exists():
time.sleep(0.01)
print('parent exited')
""")
started = time.monotonic()
with self.assertRaises(subprocess.TimeoutExpired):
run(command, self.directory, timeout=0.5)
self.assertLess(time.monotonic() - started, 8)
self.assertTrue((self.directory / 'child_stopped').exists())
if __name__ == '__main__':
unittest.main()