import json import pytest from app.mobile.protocol import Handshake, ProtocolError, fragments from app.mobile.session import SessionManager def connection(clock=lambda: 0): calls = [] manager = SessionManager(lambda method, params: calls.append(method) or {}, lambda: {"device_id": "test"}, clock=clock) assert manager.connect('a') assert not manager.connect('b') client = Handshake() result = None for part in fragments(1, 0, client.hello, 247): result = manager.accept('a', part) cipher = client.finish(result[1], server=False) return manager, cipher, calls def request(manager, cipher, mid, rid, method, params=None): raw = json.dumps(dict(id=rid, method=method, params=params or {})).encode() for part in fragments(3, mid, cipher.encrypt(raw), 247): result = manager.accept('a', part) return json.loads(cipher.decrypt(result[1])) def test_no_control_before_open(): manager, cipher, calls = connection() with pytest.raises(ProtocolError): request(manager, cipher, 1, '1', 'settings.patch') assert calls == [] def test_single_owner_duplicate_and_disconnect(): manager, cipher, calls = connection() assert request(manager, cipher, 1, '1', 'session.open', {'client_name': '手机'})['ok'] assert manager.status()['client_name'] == '手机' assert request(manager, cipher, 2, '2', 'content.play')['ok'] assert not request(manager, cipher, 3, '2', 'content.play')['ok'] assert calls == ['content.play'] manager.disconnect('b') assert manager.status()['connected'] manager.disconnect('a') assert not manager.status()['connected'] assert manager.connect('b') def test_handshake_and_idle_deadlines(): now = [0] manager, cipher, _ = connection(lambda: now[0]) now[0] = 10 assert manager.expired() manager, cipher, _ = connection(lambda: now[0]) request(manager, cipher, 1, '1', 'session.open', {'client_name': '手机'}) now[0] = 29 assert not manager.expired() now[0] = 30 assert manager.expired() def test_negotiated_receive_mtu_resets_on_disconnect(): manager, cipher, _ = connection() assert manager.peer_mtu == 23 assert request(manager, cipher, 1, '1', 'session.open', {'client_name': '手机', 'receive_mtu': 247})['ok'] assert manager.peer_mtu == 247 manager.disconnect('a') assert manager.peer_mtu == 23 @pytest.mark.parametrize('mtu', [0, 22, 518, True, '247']) def test_invalid_receive_mtu_never_opens_session(mtu): manager, cipher, _ = connection() assert not request(manager, cipher, 1, '1', 'session.open', {'client_name': '手机', 'receive_mtu': mtu})['ok'] assert not manager.opened