71 lines
3.7 KiB
Python
71 lines
3.7 KiB
Python
from types import SimpleNamespace
|
|
import struct
|
|
import pytest
|
|
|
|
from protocan.can_boot import CanBootServices, CanBootTarget, CanBootTransfer, CanBootPingExchange
|
|
from protocan.protocan import ProtoCanId
|
|
from protocan.transport import build_frame
|
|
|
|
|
|
def response(command, data, device=7):
|
|
return build_frame(ProtoCanId.build(1, 1, 3, device, 13, command), data, to_can=False)
|
|
|
|
|
|
def test_passport_and_discovery_address_filters():
|
|
service = CanBootServices(CanBootTarget(device_type=3, device=7, product_type=0x2833))
|
|
identify = response(1, struct.pack('<HBBI', 0x2833, 1, 1, 0x01010002))
|
|
assert service.decode(identify)['version'] == (1, 1, 2)
|
|
foreign = response(1, identify.data, device=8)
|
|
assert service.decode(foreign) is None
|
|
assert service.decode(foreign, discovery=True)['device'] == 8
|
|
capabilities = service.decode(response(13, struct.pack('<II', 0xFFF, 130560)))
|
|
assert capabilities['slot_capacity'] == 130560
|
|
assert capabilities['capabilities'] & (1 << 8)
|
|
assert service.decode(response(14, b'F28335-M'))['name_fragment'] == 'F28335-M'
|
|
assert service.decode(response(0x10E, b'95M02\0\0\0'))['name_fragment'] == '95M02'
|
|
memory = service.decode(response(15, struct.pack('<IHBB', 262144, 256, 1, 255)))
|
|
assert memory['bootloader'] and memory['memory_bytes'] == 262144
|
|
assert service.decode(response(0x10F, struct.pack('<II', 512, 131072)))['slot_offsets'] == (512, 131072)
|
|
pending = service.decode(response(0x20F, struct.pack('<BBBBI', 0, 1, 1, 1, 30000)))
|
|
assert pending['trial_attempted'] and pending['pending_slot'] == 1
|
|
assert service.decode(response(0x30F, struct.pack('<II', 0x3FEFC, 258)))['parameters_bytes'] == 258
|
|
assert service.decode(response(0x40F, bytes(8))) is None
|
|
discover = ProtoCanId.parse(service.discover().can_id)
|
|
assert (discover.device_type, discover.device, discover.msg_type, discover.body) == (7, 15, 13, 0)
|
|
|
|
|
|
def test_service_requests_and_transfer_limits():
|
|
target = CanBootTarget(device_type=3, device=7, product_type=0x2833, session_id=15)
|
|
service = CanBootServices(target)
|
|
request = service.request(15, 2)
|
|
assert request.data == b'\x02' and ProtoCanId.parse(request.can_id).body == 0xF0F
|
|
assert ProtoCanId.parse(service.request(8).can_id).body == 0xF08
|
|
with pytest.raises(ValueError):
|
|
service.request(5)
|
|
with pytest.raises(ValueError):
|
|
service.request(1, 3)
|
|
with pytest.raises(ValueError):
|
|
CanBootTransfer(SimpleNamespace(data=bytes(130561), version=1), target)
|
|
transfer = CanBootTransfer(SimpleNamespace(data=bytes(40), version=1), target)
|
|
assert transfer.response_timeout_ms == 15000
|
|
transfer.stage = 'data'
|
|
assert transfer.response_timeout_ms == 1500
|
|
|
|
|
|
def test_ping_exchange_only_accepts_addressed_ping_reply():
|
|
ping = CanBootPingExchange(CanBootTarget(device_type=3, device=7))
|
|
assert ProtoCanId.parse(ping.request()[0].can_id).body & 255 == 12
|
|
assert ping.feed(response(1, bytes(8))) is None
|
|
assert ping.feed(response(12, bytes([1, 0, 0, 255, 0, 2, 0, 0]), device=8)) is None
|
|
assert ping.feed(response(12, bytes([1, 0, 0, 255, 0, 2, 0, 0])))['slot_count'] == 2
|
|
|
|
|
|
def test_confirm_and_progress_status_correlate_session():
|
|
service = CanBootServices(CanBootTarget(device_type=3, device=7, session_id=5))
|
|
frame = build_frame(ProtoCanId.build(1, 1, 3, 7, 12, 0x508),
|
|
struct.pack('<BBHI', 0, 1, 123, 0x12345678), to_can=False)
|
|
reply = service.decode(frame)
|
|
assert reply['status'] == 0 and reply['command'] == 8 and reply['next_block'] == 123
|
|
assert service.decode(frame, discovery=True) is None
|
|
assert CanBootServices(CanBootTarget(device_type=3, device=7, session_id=6)).decode(frame) is None
|