Files
StarPilot/openpilot/system/updated/tests/test_unpublished_branch.py
T
firestar5683 a82935f326 User interfaces and Android Auto
Integrate onroad views, configurable widgets, local settings, steering-profile contracts, Bluetooth and Android Auto with their device and runtime services.

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: Prabhaav Pillai <prabhaav@msu.edu>
Co-authored-by: Shane Smiskol <shane@smiskol.com>
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: pharmacomaniac <blittle65@gmail.com>

Co-authored-by: prabhaavp <prabhaav@msu.edu>
2026-10-14 20:02:39 -05:00

122 lines
5.0 KiB
Python

"""An unpublished local target is not a failed download or a phantom update."""
import subprocess
import tempfile
import unittest
from pathlib import Path
from unittest.mock import Mock
from openpilot.system.updated.tests.test_vendored_update import load_updater
TARGET = "local-domathon"
CURRENT = "a" * 40
REMOTE = "b" * 40
class TestUnpublishedBranch(unittest.TestCase):
def setUp(self):
self.temporary = tempfile.TemporaryDirectory()
self.addCleanup(self.temporary.cleanup)
self.root = Path(self.temporary.name)
self.merged = self.root / "merged"
self.merged.mkdir()
self.finalized = self.root / "finalized"
self.updated = load_updater()
self.updated.OVERLAY_MERGED = str(self.merged)
self.updated.FINALIZED = str(self.finalized)
self.updated.BASEDIR = str(self.merged)
self.updated.setup_git_options = Mock()
self.updated.set_consistent_flag = Mock()
self.updater = self.updated.Updater()
self.updater.params.values["UpdaterTargetBranch"] = TARGET
self.updater.get_branch = Mock(return_value=TARGET)
self.updater.get_commit_hash = Mock(return_value=CURRENT)
self.commands = []
self.remote_heads = f"{REMOTE}\trefs/heads/another-branch\n"
def run(command, cwd):
self.assertEqual(cwd, str(self.merged))
self.commands.append(command)
if command == ["git", "ls-remote", "--heads", "origin"]:
return self.remote_heads
if command == ["git", "ls-remote", "origin", "HEAD"]:
return f"{REMOTE}\tHEAD\n"
raise AssertionError(f"Unexpected command: {command}")
self.updated.run = run
def test_check_clock_requires_successful_remote_check(self):
self.assertNotIn("UpdaterLastCheckTime", self.updater.params.values)
self.updater.check_for_update()
checked = self.updater.params.values["UpdaterLastCheckTime"]
self.updated.run = Mock(side_effect=subprocess.CalledProcessError(1, "git ls-remote"))
with self.assertRaises(subprocess.CalledProcessError):
self.updater.check_for_update()
self.assertEqual(self.updater.params.values["UpdaterLastCheckTime"], checked)
self.assertNotIn("LastUpdateTime", self.updater.params.values)
def test_missing_target_never_becomes_a_branch_or_fetches(self):
self.updater.check_for_update()
self.assertEqual(self.updater.branches, {"another-branch": REMOTE})
self.assertFalse(self.updater.update_available)
self.finalized.mkdir()
(self.finalized / ".overlay_consistent").touch()
self.assertFalse(self.updater.update_ready)
self.assertFalse(self.updater.fetch_update())
self.assertNotIn(TARGET, self.updater.branches)
self.assertEqual(self.commands.count(["git", "ls-remote", "--heads", "origin"]), 1)
self.updated.set_consistent_flag.assert_not_called()
self.assertNotIn("UpdaterState", self.updater.params.values)
def test_direct_fetch_checks_before_any_mutation(self):
self.assertFalse(self.updater.fetch_update())
self.assertEqual(self.updater.branches, {"another-branch": REMOTE})
self.updated.set_consistent_flag.assert_not_called()
self.assertNotIn("UpdateAvailable", self.updater.params.values)
def test_published_same_and_different_commit(self):
self.remote_heads += f"{CURRENT}\trefs/heads/{TARGET}\n"
self.updater.check_for_update()
self.assertFalse(self.updater.update_available)
self.assertEqual(self.updater.branches[TARGET], CURRENT)
self.remote_heads = f"{REMOTE}\trefs/heads/{TARGET}\n"
self.updater.check_for_update()
self.assertTrue(self.updater.update_available)
self.assertEqual(self.updater.branches[TARGET], REMOTE)
self.remote_heads = f"{REMOTE}\trefs/heads/another-branch\n"
self.updater.check_for_update()
self.assertFalse(self.updater.update_available)
self.assertNotIn(TARGET, self.updater.branches)
def test_stale_finalized_overlay_is_not_ready(self):
self.remote_heads = f"{REMOTE}\trefs/heads/{TARGET}\n"
self.updater.check_for_update()
self.finalized.mkdir()
(self.finalized / ".overlay_consistent").touch()
self.assertFalse(self.updater.update_ready)
self.updater.get_commit_hash = Mock(side_effect=lambda path: REMOTE if path == str(self.finalized) else CURRENT)
self.assertTrue(self.updater.update_ready)
def test_remote_error_remains_an_error(self):
self.remote_heads = f"{REMOTE}\trefs/heads/{TARGET}\n"
self.updater.check_for_update()
self.assertTrue(self.updater.update_available)
def failed_run(command, cwd):
if command == ["git", "ls-remote", "--heads", "origin"]:
raise subprocess.CalledProcessError(128, command, output="network failed")
return f"{REMOTE}\tHEAD\n"
self.updated.run = failed_run
self.updater._branches_checked = False
with self.assertRaises(subprocess.CalledProcessError):
self.updater.fetch_update()
self.assertFalse(self.updater._branches_checked)
self.assertFalse(self.updater.update_available)
self.updated.set_consistent_flag.assert_not_called()
if __name__ == "__main__":
unittest.main()