mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 13:33:42 +08:00
a531afd02a
Expose pairing readiness and coordinate adapter hand-offs with Android Auto. Show app pairings separately, support individual removal, and improve pairing controls on both comma screens. Add Galaxy companion endpoints and web asset manifests, preserve the plain camera look, and fix headless speed-limit shapes.
77 lines
3.8 KiB
Python
77 lines
3.8 KiB
Python
from unittest.mock import Mock, patch
|
|
|
|
import pytest
|
|
|
|
from openpilot.starpilot.bluetooth.native_owner import NativeBluetoothOwner
|
|
from openpilot.starpilot.bluetooth.owner import AdapterBusyElsewhere, BluetoothOwner, BluetoothRejected
|
|
|
|
|
|
@pytest.mark.parametrize('operation, fields', [
|
|
('scan', {}), ('stop_scan', {}), ('pair', {'address': 'AA:BB:CC:DD:EE:FF', 'session': ('large', 'one')}),
|
|
('connect', {'address': 'AA:BB:CC:DD:EE:FF'}), ('disconnect', {'address': 'AA:BB:CC:DD:EE:FF'}),
|
|
('forget', {'address': 'AA:BB:CC:DD:EE:FF'}), ('power', {'enabled': False}),
|
|
])
|
|
def test_busy_native_owner_delegates_all_controls(operation, fields):
|
|
owner = NativeBluetoothOwner(lambda: True)
|
|
call = Mock(return_value=(200, {'devices': []}))
|
|
with patch.object(BluetoothOwner, 'request', side_effect=AdapterBusyElsewhere('AA owns radio')), \
|
|
patch('openpilot.starpilot.galaxy_bluetooth.phone_ui.galaxy_call', return_value=call) as factory:
|
|
assert owner.request(operation, **fields) == {'devices': []}
|
|
payload = {'operation': operation, **{k: v for k, v in fields.items() if k != 'session'}}
|
|
call.assert_called_once_with('POST', '/api/bluetooth/action', payload)
|
|
owner.snapshot(session=('large', 'one'))
|
|
call.assert_called_with('GET', '/api/bluetooth/status')
|
|
factory.assert_called_once()
|
|
|
|
|
|
def test_pairing_poll_response_and_close_use_the_same_galaxy_session():
|
|
owner = NativeBluetoothOwner(lambda: True)
|
|
call = Mock(return_value=(200, {'devices': [], 'pairing': {'state': 'pairing'}}))
|
|
with patch.object(BluetoothOwner, 'request', side_effect=AdapterBusyElsewhere('busy')) as local, \
|
|
patch('openpilot.starpilot.galaxy_bluetooth.phone_ui.galaxy_call', return_value=call) as factory:
|
|
owner.request('pair', address='AA:BB:CC:DD:EE:FF', session=('large', 'one'))
|
|
owner.snapshot(session=('large', 'one'))
|
|
owner.request('pairing_response', prompt_id='a' * 32, accepted=True, value='', session=('large', 'one'))
|
|
call.assert_called_with('POST', '/api/bluetooth/action',
|
|
{'operation': 'pairing_response', 'promptId': 'a' * 32, 'accepted': True, 'value': ''})
|
|
owner.close()
|
|
call.assert_called_with('POST', '/api/bluetooth/action', {'operation': 'cancel_pair'})
|
|
local.assert_called_once()
|
|
factory.assert_called_once()
|
|
assert owner.galaxy is None
|
|
|
|
|
|
@pytest.mark.parametrize('error', [BluetoothRejected('park first', code='park_required'),
|
|
BluetoothRejected('Pairing is in progress', code='busy')])
|
|
def test_local_denials_never_switch_to_galaxy(error):
|
|
owner = NativeBluetoothOwner(lambda: True)
|
|
with patch.object(BluetoothOwner, 'request', side_effect=error), \
|
|
patch('openpilot.starpilot.galaxy_bluetooth.phone_ui.galaxy_call') as factory:
|
|
with pytest.raises(BluetoothRejected):
|
|
owner.request('scan')
|
|
factory.assert_not_called()
|
|
assert owner.galaxy is None
|
|
|
|
|
|
def test_delegated_page_open_never_scans():
|
|
owner = NativeBluetoothOwner(lambda: True)
|
|
owner.galaxy = Mock(return_value=(200, {'devices': []}))
|
|
assert owner.request('scan', delegate=False) == {'devices': []}
|
|
owner.galaxy.assert_called_once_with('GET', '/api/bluetooth/status')
|
|
|
|
|
|
def test_denials_do_not_retry_through_a_different_owner():
|
|
owner = NativeBluetoothOwner(lambda: True)
|
|
with patch.object(BluetoothOwner, 'request', side_effect=BluetoothRejected('park first', code='park_required')), \
|
|
patch('openpilot.starpilot.galaxy_bluetooth.phone_ui.galaxy_call') as factory:
|
|
with pytest.raises(BluetoothRejected, match='park first'):
|
|
owner.request('power', enabled=False)
|
|
factory.assert_not_called()
|
|
call = Mock(return_value=(409, {'code': 'busy'}))
|
|
owner.galaxy = call
|
|
with patch.object(BluetoothOwner, 'request') as local:
|
|
with pytest.raises(BluetoothRejected):
|
|
owner.request('scan')
|
|
local.assert_not_called()
|
|
call.assert_called_once()
|