mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 05:23:41 +08:00
a82935f326
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>
111 lines
4.8 KiB
Python
111 lines
4.8 KiB
Python
import os
|
|
from pathlib import Path
|
|
import tempfile
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from openpilot.starpilot.bluetooth.radio_preference import RADIO_PREFERENCE, RadioPreference
|
|
|
|
|
|
class RadioPreferenceTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.temp = tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.temp.cleanup)
|
|
self.root = Path(self.temp.name)
|
|
self.namespace = self.root / 'd_tmp'
|
|
self.namespace.mkdir()
|
|
(self.root / 'd').symlink_to(self.namespace.name)
|
|
self.preference = RadioPreference(self.root / 'd' / 'BluetoothEnabled')
|
|
|
|
def test_service_file_is_global_not_application_prefix(self):
|
|
with patch.dict(os.environ, {'OPENPILOT_PREFIX': 'private-drive'}):
|
|
self.assertEqual(RadioPreference().path, Path('/data/params/d/BluetoothEnabled'))
|
|
self.assertEqual(RADIO_PREFERENCE, RadioPreference().path)
|
|
|
|
def test_read_does_not_create_or_enable_and_matches_service_newline_semantics(self):
|
|
self.assertFalse(self.preference.enabled())
|
|
self.assertFalse(self.preference.path.exists())
|
|
for value, enabled in ((b'1', True), (b'1\n\n', True), (b'0', False), (b'1 ', False), (b'', False)):
|
|
with self.subTest(value=value):
|
|
self.preference.path.write_bytes(value)
|
|
self.assertEqual(self.preference.enabled(), enabled)
|
|
self.assertEqual(self.preference.path.read_bytes(), value)
|
|
|
|
def test_explicit_change_is_atomic_and_rollback_restores_exact_bytes(self):
|
|
for previous in (None, b'0\n', b'1\n\n', b''):
|
|
with self.subTest(previous=previous):
|
|
self.preference.path.unlink(missing_ok=True)
|
|
if previous is not None:
|
|
self.preference.path.write_bytes(previous)
|
|
change = self.preference.begin(True)
|
|
self.assertEqual(self.preference.path.read_bytes() if self.preference.path.exists() else None, previous)
|
|
change.apply()
|
|
self.assertEqual(self.preference.path.read_bytes(), b'1')
|
|
change.verify()
|
|
self.assertTrue(change.rollback())
|
|
self.assertEqual(self.preference.path.read_bytes() if self.preference.path.exists() else None, previous)
|
|
self.assertFalse(list(self.namespace.glob('.bluetooth-enable-*')))
|
|
|
|
def test_namespace_switch_never_writes_or_rolls_back_into_new_namespace(self):
|
|
next_namespace = self.root / 'next'
|
|
next_namespace.mkdir()
|
|
change = self.preference.begin(True)
|
|
change.apply()
|
|
self.preference.path.parent.unlink()
|
|
self.preference.path.parent.symlink_to(next_namespace.name)
|
|
with self.assertRaises(OSError):
|
|
change.verify()
|
|
self.assertFalse(change.rollback())
|
|
self.assertEqual((self.namespace / 'BluetoothEnabled').read_bytes(), b'1')
|
|
self.assertFalse((next_namespace / 'BluetoothEnabled').exists())
|
|
|
|
def test_namespace_switch_before_apply_is_rejected(self):
|
|
change = self.preference.begin(True)
|
|
next_namespace = self.root / 'next'
|
|
next_namespace.mkdir()
|
|
self.preference.path.parent.unlink()
|
|
self.preference.path.parent.symlink_to(next_namespace.name)
|
|
with self.assertRaises(OSError):
|
|
change.apply()
|
|
self.assertFalse((self.namespace / 'BluetoothEnabled').exists())
|
|
self.assertFalse((next_namespace / 'BluetoothEnabled').exists())
|
|
|
|
def test_external_replace_with_same_bytes_is_not_owned_for_rollback(self):
|
|
change = self.preference.begin(True)
|
|
change.apply()
|
|
replacement = self.namespace / 'external'
|
|
replacement.write_bytes(b'1')
|
|
replacement.replace(self.preference.path)
|
|
self.assertFalse(change.rollback())
|
|
self.assertEqual(self.preference.path.read_bytes(), b'1')
|
|
|
|
def test_external_change_before_apply_is_not_overwritten(self):
|
|
change = self.preference.begin(True)
|
|
self.preference.path.write_bytes(b'0\n')
|
|
with self.assertRaises(OSError):
|
|
change.apply()
|
|
self.assertEqual(self.preference.path.read_bytes(), b'0\n')
|
|
|
|
def test_unsafe_or_oversized_files_are_rejected_before_changes(self):
|
|
target = self.root / 'other'
|
|
target.write_bytes(b'0')
|
|
self.preference.path.symlink_to(target)
|
|
with self.assertRaises(OSError):
|
|
self.preference.begin(True)
|
|
self.assertEqual(target.read_bytes(), b'0')
|
|
self.preference.path.unlink()
|
|
self.preference.path.write_bytes(b'0' * 17)
|
|
with self.assertRaises(OSError):
|
|
self.preference.begin(True)
|
|
self.assertEqual(self.preference.path.read_bytes(), b'0' * 17)
|
|
|
|
def test_failed_replace_preserves_original_bytes(self):
|
|
self.preference.path.write_bytes(b'0\n')
|
|
change = self.preference.begin(True)
|
|
with patch('openpilot.starpilot.bluetooth.radio_preference.os.replace', side_effect=OSError('disk full')):
|
|
with self.assertRaises(OSError):
|
|
change.apply()
|
|
self.assertFalse(change.rollback())
|
|
self.assertEqual(self.preference.path.read_bytes(), b'0\n')
|
|
self.assertFalse(list(self.namespace.glob('.bluetooth-enable-*')))
|