VulpesOS/tundra/tests/test_wifi_control.py
OverSu 1311bed5e9 Release Preview 20 shared desktop, Android and Sargo updates
Restore Gaia settings and media workflows, extend native network adapters, and align the APK payload. Generate French/English changelogs and website entries from the simplified JSON source.

Validation: shared JS and Tundra unit tests; desktop workflows and persistence; signed APK payload parity; Sargo RAM and installed startup with boot readback. Android runtime qualification is recorded separately.
2026-10-13 00:19:45 +02:00

142 lines
7.6 KiB
Python

# SPDX-License-Identifier: MPL-2.0
import importlib.util
import json
from pathlib import Path
import socket
import stat
import struct
import tempfile
import threading
from types import SimpleNamespace
import unittest
from unittest.mock import patch
spec = importlib.util.spec_from_file_location('wifi', Path(__file__).resolve().parents[1]/'runtime/wifi-control.py')
wifi = importlib.util.module_from_spec(spec)
spec.loader.exec_module(wifi)
AP = {'id': '/org/freedesktop/NetworkManager/AccessPoint/7',
'ssid': 'Test: réseau\\', 'security': 'wpa-psk', 'signal': 75}
class WifiTests(unittest.TestCase):
def test_nmcli_escaped_names_and_enterprise(self):
raw = AP['id'] + r':Test\: réseau\\:75:WPA2:*' + '\n'
raw += '/org/freedesktop/NetworkManager/AccessPoint/8:Enterprise:60:WPA2 802.1X:\n'
with patch.object(wifi, 'nm', return_value=SimpleNamespace(returncode=0, stdout=raw)):
result = wifi.networks()
self.assertEqual(result[0]['ssid'], AP['ssid'])
self.assertTrue(result[0]['connected'])
self.assertEqual(result[1]['security'], 'unsupported')
def test_connection_information_uses_validated_address_and_actual_bitrate(self):
def nm(*args, **kwargs):
value='invalid\n192.0.2.4/24\n' if args[1]=='IP4.ADDRESS' else '/org/freedesktop/NetworkManager/Devices/4\n'
return SimpleNamespace(returncode=0,stdout=value)
with patch.object(wifi,'nm',side_effect=nm), patch.object(wifi.subprocess,'run',return_value=SimpleNamespace(returncode=0,stdout='{"data":[351000]}')):
self.assertEqual(wifi.connection_info(),{'ipAddress':'192.0.2.4','linkSpeed':351})
with patch.object(wifi,'nm',return_value=SimpleNamespace(returncode=0,stdout='/invalid/path')), patch.object(wifi.subprocess,'run') as run:
self.assertEqual(wifi.connection_info(),{})
run.assert_not_called()
def test_secret_persists_only_after_success(self):
for fail in (False, True):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
commands = []
def nm(*args, **kwargs):
commands.append(args)
if args[:2] == ('connection', 'load'):
file = Path(args[2])
self.assertEqual(stat.S_IMODE(file.stat().st_mode), 0o600)
self.assertIn('psk=testpassword', file.read_text())
return SimpleNamespace(returncode=int(fail and args[:2] == ('connection', 'up')))
with patch.object(wifi, 'networks', return_value=[AP]), patch.object(wifi, 'nm', side_effect=nm):
request = {'operation':'connect', 'id':AP['id'], 'password':'testpassword'}
if fail:
with self.assertRaisesRegex(wifi.WifiError, 'WIFI_CONNECT_FAILED'):
wifi.dispatch(request, root)
else:
self.assertTrue(wifi.dispatch(request, root)['connected'])
files=list(root.iterdir())
self.assertEqual(len(files), 0 if fail else 1)
if not fail:
self.assertIn('autoconnect=true', files[0].read_text())
self.assertEqual(wifi.saved_profiles(root)[0]['ssid'], AP['ssid'])
self.assertNotIn('testpassword', repr(commands))
def test_remember_reconnect_failed_password_and_forget(self):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
with patch.object(wifi, 'networks', return_value=[AP]), patch.object(wifi, 'nm', return_value=SimpleNamespace(returncode=0)):
wifi.dispatch({'operation':'connect','id':AP['id'],'password':'firstpassword'},root)
stored = wifi.dispatch({'operation':'known'},root)['networks'][0]
self.assertNotIn('password', stored)
wifi.dispatch({'operation':'connect','id':AP['id']},root)
target = next(root.iterdir())
before = target.read_text()
def failing(*args, **kwargs):
return SimpleNamespace(returncode=int(args[:2]==('connection','up')))
with patch.object(wifi, 'nm', side_effect=failing):
with self.assertRaises(wifi.WifiError):
wifi.dispatch({'operation':'connect','id':AP['id'],'password':'wrongpassword'},root)
self.assertEqual(target.read_text(),before)
wifi.dispatch({'operation':'forget','id':stored['id']},root)
self.assertEqual(list(root.iterdir()),[])
def test_rejects_commands_injection_and_unobserved_networks(self):
with patch.object(wifi, 'nm') as command:
for request in ({'operation':'execute'}, {'operation':'scan','command':'id'}, []):
with self.assertRaises(wifi.WifiError):
wifi.dispatch(request)
command.assert_not_called()
with patch.object(wifi, 'networks', return_value=[]):
with self.assertRaisesRegex(wifi.WifiError, 'WIFI_NETWORK_GONE'):
wifi.dispatch({'operation':'connect','id':'/tmp/hostile'})
for password in ('short', 'testpass\n[connection]', 'x'*100):
with self.assertRaises(wifi.WifiError):
wifi.profile_text(AP, password, 'test')
def test_hidden_network_uses_encoded_ssid_and_private_profile(self):
with tempfile.TemporaryDirectory() as folder, patch.object(wifi,'nm',return_value=SimpleNamespace(returncode=0)):
root=Path(folder)
wifi.dispatch({'operation':'connectHidden','ssid':'Hidden; réseau','security':'wpa-psk','password':'testpassword'},root)
saved=next(root.iterdir())
self.assertIn('hidden=true',saved.read_text())
self.assertEqual(stat.S_IMODE(saved.stat().st_mode),0o600)
self.assertEqual(wifi.saved_profiles(root)[0]['ssid'],'Hidden; réseau')
for ssid in ('','x'*33,'é'*17):
with tempfile.TemporaryDirectory() as folder, self.assertRaises(wifi.WifiError):
wifi.dispatch({'operation':'connectHidden','ssid':ssid,'security':'open'},Path(folder))
def test_socket_round_trip_and_limits(self):
a, b = socket.socketpair()
with a, b, patch.object(wifi, 'dispatch', return_value={'networks':[]}) as dispatch:
# Peer credential enforcement is independent of the CI user's uid.
class Peer:
def getsockopt(self, *args): return struct.pack('3i', 123, 32011, 32011)
def __getattr__(self, name): return getattr(b, name)
thread = threading.Thread(target=wifi.handle, args=(Peer(),))
thread.start()
a.sendall(b'{"operation":"scan"}\n')
self.assertEqual(wifi.receive(a, 65536), {'result':{'networks':[]}})
thread.join(2)
self.assertFalse(thread.is_alive())
dispatch.assert_called_once_with({'operation':'scan'})
a, b = socket.socketpair()
with a, b:
a.sendall(b'12345\n')
with self.assertRaises(wifi.WifiError): wifi.receive(b, 4)
def test_unauthorized_peer_never_dispatches(self):
class Peer:
def settimeout(self, _): pass
def getsockopt(self, *args): return struct.pack('3i', 123, 65534, 65534)
def sendall(self, data): self.reply = json.loads(data)
peer = Peer()
with patch.object(wifi, 'dispatch') as dispatch:
wifi.handle(peer)
dispatch.assert_not_called()
self.assertEqual(peer.reply, {'error':'PERMISSION_DENIED'})
if __name__ == '__main__': unittest.main()