VulpesOS/tundra/tests/test_wifi_control.py
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

120 lines
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_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_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()