Skip to content

Commit b2fb32e

Browse files
authored
Extend types coverage. (#80)
1 parent 0813e7f commit b2fb32e

File tree

2 files changed

+147
-3
lines changed

2 files changed

+147
-3
lines changed

tests/test_types.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from unittest import mock
2+
3+
import pytest
4+
15
import zigpy_deconz.types as t
26

37

@@ -85,3 +89,144 @@ def test_key():
8589
assert key == [49, 57, 99, 50, 48, 101, 97, 99, 54, 54, 50, 99, 97, 56, 48, 53]
8690

8791
assert key.serialize() == data
92+
93+
94+
def test_bytes():
95+
data = b'abcde\x00\xff'
96+
97+
r, rest = t.Bytes.deserialize(data)
98+
assert rest == b''
99+
assert r == data
100+
101+
assert r.serialize() == data
102+
103+
104+
def test_lvbytes():
105+
data = b'abcde\x00\xff'
106+
extra = b'\xffrest of the data\x00'
107+
108+
r, rest = t.LVBytes.deserialize(len(data).to_bytes(2, "little") + data + extra)
109+
assert rest == extra
110+
assert r == data
111+
112+
assert r.serialize() == len(data).to_bytes(2, "little") + data
113+
114+
115+
def test_struct():
116+
class TestStruct(t.Struct):
117+
_fields = [("a", t.uint8_t), ("b", t.uint8_t)]
118+
119+
ts = TestStruct()
120+
ts.a = t.uint8_t(0xAA)
121+
ts.b = t.uint8_t(0xBB)
122+
ts2 = TestStruct(ts)
123+
assert ts2.a == ts.a
124+
assert ts2.b == ts.b
125+
126+
r = repr(ts)
127+
assert "TestStruct" in r
128+
assert r.startswith("<") and r.endswith(">")
129+
130+
s = ts2.serialize()
131+
assert s == b"\xaa\xbb"
132+
133+
extra = b"\x00extra data\xff"
134+
d, rest = TestStruct.deserialize(s + extra)
135+
assert rest == extra
136+
assert d.a == ts.a
137+
assert d.b == ts.b
138+
139+
140+
def test_list():
141+
class TestList(t.List):
142+
_itemtype = t.uint16_t
143+
144+
r = TestList([1, 2, 3, 0x55aa])
145+
assert r.serialize() == b'\x01\x00\x02\x00\x03\x00\xaa\x55'
146+
147+
148+
def test_list_deserialize():
149+
class TestList(t.List):
150+
_itemtype = t.uint16_t
151+
152+
data = b"\x34\x12\x55\xaa\x89\xab"
153+
extra = b"\x00\xff"
154+
155+
r, rest = TestList.deserialize(data + extra)
156+
assert rest == b''
157+
assert r[0] == 0x1234
158+
assert r[1] == 0xaa55
159+
assert r[2] == 0xab89
160+
assert r[3] == 0xff00
161+
162+
163+
def test_fixed_list():
164+
class TestList(t.FixedList):
165+
_length = 3
166+
_itemtype = t.uint16_t
167+
168+
with pytest.raises(AssertionError):
169+
r = TestList([1, 2, 3, 0x55aa])
170+
r.serialize()
171+
172+
with pytest.raises(AssertionError):
173+
r = TestList([1, 2])
174+
r.serialize()
175+
176+
r = TestList([1, 2, 3])
177+
178+
assert r.serialize() == b'\x01\x00\x02\x00\x03\x00'
179+
180+
181+
def test_fixed_list_deserialize():
182+
class TestList(t.FixedList):
183+
_length = 3
184+
_itemtype = t.uint16_t
185+
186+
data = b"\x34\x12\x55\xaa\x89\xab"
187+
extra = b"\x00\xff"
188+
189+
r, rest = TestList.deserialize(data + extra)
190+
assert rest == extra
191+
assert r[0] == 0x1234
192+
assert r[1] == 0xaa55
193+
assert r[2] == 0xab89
194+
195+
196+
def test_eui64():
197+
r = t.EUI64([0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08])
198+
ieee = '08:09:0a:0b:0c:0d:0e:0f'
199+
assert repr(r) == ieee
200+
i = {}
201+
i[r] = mock.sentinel.data
202+
203+
204+
def test_hexrepr():
205+
class TestHR(t.HexRepr, t.uint16_t):
206+
pass
207+
208+
i = TestHR(0xaa55)
209+
assert repr(i) == "0xaa55"
210+
assert str(i) == "0xaa55"
211+
212+
213+
def test_addr_ep_nwk():
214+
data = b"\x02\xaa\x55\xcc"
215+
extra = b"\x00extra data\xff"
216+
217+
r, rest = t.DeconzAddressEndpoint.deserialize(data + extra)
218+
assert rest == extra
219+
assert r.address_mode == t.ADDRESS_MODE.NWK
220+
assert r.address == 0x55aa
221+
assert r.endpoint == 0xcc
222+
223+
224+
def test_addr_ep_ieee():
225+
data = b"\x0387654321\xcc"
226+
extra = b"\x00extra data\xff"
227+
228+
r, rest = t.DeconzAddressEndpoint.deserialize(data + extra)
229+
assert rest == extra
230+
assert r.address_mode == t.ADDRESS_MODE.IEEE
231+
assert repr(r.address) == "31:32:33:34:35:36:37:38"
232+
assert r.endpoint == 0xcc

zigpy_deconz/types.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ def serialize(self):
2828

2929
@classmethod
3030
def deserialize(cls, data, byteorder='little'):
31-
bytes = int.from_bytes(data[:2], byteorder)
32-
s = data[2:bytes + 2]
33-
return s, data[bytes + 2:]
31+
length, data = uint16_t.deserialize(data)
32+
return cls(data[:length]), data[length:]
3433

3534

3635
class int_t(int):

0 commit comments

Comments
 (0)