Add bounded X4 Bluetooth wake and record Android recovery proof
This commit is contained in:
@@ -53,6 +53,30 @@ class OptionsTests(unittest.TestCase):
|
||||
{"acknowledged": True, "present": False, "value": None},
|
||||
)
|
||||
|
||||
def test_captured_heartbeat_is_not_an_options_response(self):
|
||||
heartbeat = bytes.fromhex("07000000050000")
|
||||
raw = reply(field(1, 95) + field(2, field(95, 1)))
|
||||
reader = codec.PacketReader()
|
||||
self.assertEqual(reader.feed(heartbeat[:4]), [])
|
||||
self.assertEqual(reader.feed(heartbeat[4:]), [])
|
||||
self.assertEqual(reader.heartbeats, 1)
|
||||
packets = reader.feed(heartbeat + raw[:9])
|
||||
self.assertEqual(packets, [])
|
||||
packets = reader.feed(raw[9:] + heartbeat)
|
||||
self.assertEqual(len(packets), 1)
|
||||
self.assertEqual(reader.heartbeats, 3)
|
||||
self.assertEqual(codec.decode_options_response(packets[0], 1, [95])[95]["value"], 1)
|
||||
|
||||
def test_short_control_packets_are_exact_and_bounded(self):
|
||||
for raw in ("07000000040000", "07000000050100", "0800000005000000"):
|
||||
with self.assertRaises(ValueError):
|
||||
codec.PacketReader().feed(bytes.fromhex(raw))
|
||||
reader = codec.PacketReader()
|
||||
for _ in range(64):
|
||||
self.assertEqual(reader.feed(bytes.fromhex("07000000050000")), [])
|
||||
with self.assertRaises(ValueError):
|
||||
reader.feed(bytes.fromhex("07000000050000"))
|
||||
|
||||
def test_explicit_zero_and_packed_option_list(self):
|
||||
packet = codec.PacketReader().feed(reply(field(1, b"\x5f") + field(2, field(95, 0))))[0]
|
||||
self.assertEqual(codec.decode_options_response(packet, 1, [95])[95]["value"], 0)
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
"""Synthetic identity and exact wake payload; no host Bluetooth access."""
|
||||
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
directory = Path(__file__).resolve().parents[1] / "packaging"
|
||||
sys.path.insert(0, str(directory))
|
||||
spec = importlib.util.spec_from_file_location("wake_under_test", directory / "ble_wake.py")
|
||||
wake = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(wake)
|
||||
sys.path.pop(0)
|
||||
|
||||
|
||||
def target(serial="SYNTHETIC34UQG5"):
|
||||
return {
|
||||
"serial": serial,
|
||||
"device_id": "instax4_" + hashlib.sha256(serial.encode()).hexdigest()[:32],
|
||||
"bluetooth_address": "02:00:00:00:00:01",
|
||||
"wakeup_enabled": True,
|
||||
}
|
||||
|
||||
|
||||
class WakeTests(unittest.TestCase):
|
||||
def test_spec_vector_has_one_company_id_and_fits_legacy_advertisement(self):
|
||||
data = wake.wake_payload(target())
|
||||
self.assertEqual(data.hex(), "0215094f5242495409ff0f0033345551473500000000e401")
|
||||
self.assertEqual(len(data) + 7, 31)
|
||||
|
||||
def test_unknown_wakeup_suffix_only_and_wrong_identity_are_rejected(self):
|
||||
for value in (
|
||||
target("34UQG5"),
|
||||
dict(target(), device_id="instax4_" + "0" * 32),
|
||||
dict(target(), wakeup_enabled=False),
|
||||
dict(target(), bluetooth_address="unknown"),
|
||||
):
|
||||
with self.assertRaises(ValueError):
|
||||
wake.wake_payload(value)
|
||||
|
||||
def test_sdk_identity_requires_full_serial_and_correct_mode(self):
|
||||
value = target()
|
||||
device = {"idVendor": "2e1a", "idProduct": "0002", "serial": value["serial"]}
|
||||
self.assertTrue(wake.matching_sdk({"devices": [device]}, value["device_id"]))
|
||||
for changed in (
|
||||
dict(device, serial="34UQG5"),
|
||||
dict(device, idVendor="070a", idProduct="4026"),
|
||||
):
|
||||
self.assertFalse(wake.matching_sdk({"devices": [changed]}, value["device_id"]))
|
||||
|
||||
def test_present_sdk_owner_blocks_before_any_bluetooth_access(self):
|
||||
with (
|
||||
patch.object(wake, "assert_no_usb_owner", side_effect=RuntimeError("owned")),
|
||||
patch.object(wake, "Inspector") as inspector,
|
||||
):
|
||||
with self.assertRaisesRegex(RuntimeError, "owned"):
|
||||
wake.run(target(), {})
|
||||
inspector.assert_not_called()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user