Coverage for tests/comm/test_cstruct.py: 100%
63 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-07-10 13:43 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-07-10 13:43 +0000
1# The MIT License (MIT)
2#
3# Copyright (c) 2021 RSK Labs Ltd
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy of
6# this software and associated documentation files (the "Software"), to deal in
7# the Software without restriction, including without limitation the rights to
8# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9# of the Software, and to permit persons to whom the Software is furnished to do
10# so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in all
13# copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21# SOFTWARE.
23from unittest import TestCase
24from parameterized import parameterized
25from comm.cstruct import CStruct
27import logging
29logging.disable(logging.CRITICAL)
32class RandomBisStruct(CStruct):
33 """
34 random_bis_t
36 uint16_t another_double
37 uint8_t single_arr 10
38 uint32_t another_quad
39 """
42class RandomTrisStruct(CStruct):
43 """
44 random_tris_t
46 uint8_t arr_one 2
47 uint8_t arr_two 3
48 """
51class RandomStruct(CStruct):
52 """
53 random_t
55 uint8_t single_val
56 uint16_t double_val
57 uint32_t quad_val
58 uint64_t oct_val
60 random_bis_t other_random
61 random_tris_t yet_other_random
62 """
65class Invalid1(CStruct):
66 """
67 invalid_1
69 nonexistent_type something
70 """
73class Invalid2(CStruct):
74 """
75 invalid_2
77 uint32_t withlength 5
78 """
81class ValidWithInvalid(CStruct):
82 """
83 valid_with_invalid
85 uint8_t a_number
86 uint16_t another_number
87 invalid_2 something_invalid
88 """
91class TestCStruct(TestCase):
92 def setUp(self):
93 self.packed = bytes.fromhex(
94 "99" # single_val
95 "0102" # double_val
96 "03040506" # quad_val
97 "0708090a0b0c0d0e" # oct_val
98 "8899" # another_double
99 "00112233445566778899" # single_arr
100 "d1d2d3d4" # another_quad
101 "aabb" # arr_one
102 "ccddee" # arr_two
103 )
105 def test_expected_sizes(self):
106 self.assertEqual(16, RandomBisStruct.get_bytelength())
107 self.assertEqual(5, RandomTrisStruct.get_bytelength())
108 self.assertEqual(15 +
109 RandomBisStruct.get_bytelength() +
110 RandomTrisStruct.get_bytelength(),
111 RandomStruct.get_bytelength())
113 def test_parsing_default(self):
114 parsed = RandomStruct(self.packed)
116 self.assertEqual(0x99, parsed.single_val)
117 self.assertEqual(0x0201, parsed.double_val)
118 self.assertEqual(0x06050403, parsed.quad_val)
119 self.assertEqual(0x0e0d0c0b0a090807, parsed.oct_val)
121 self.assertEqual(0x9988, parsed.other_random.another_double)
122 self.assertEqual(bytes.fromhex("00112233445566778899"),
123 parsed.other_random.single_arr)
124 self.assertEqual(0xd4d3d2d1, parsed.other_random.another_quad)
126 self.assertEqual(bytes.fromhex("aabb"), parsed.yet_other_random.arr_one)
127 self.assertEqual(bytes.fromhex("ccddee"), parsed.yet_other_random.arr_two)
129 self.assertEqual({
130 "single_val": 0x99,
131 "double_val": 0x0201,
132 "quad_val": 0x06050403,
133 "oct_val": 0x0e0d0c0b0a090807,
134 "other_random": {
135 "another_double": 0x9988,
136 "single_arr": "00112233445566778899",
137 "another_quad": 0xd4d3d2d1,
138 },
139 "yet_other_random": {
140 "arr_one": "aabb",
141 "arr_two": "ccddee",
142 }
143 }, parsed.to_dict())
145 def test_parsing_little_offset(self):
146 parsed = RandomStruct(b"thisisrandom" + self.packed, offset=12, little=True)
148 self.assertEqual(0x99, parsed.single_val)
149 self.assertEqual(0x0201, parsed.double_val)
150 self.assertEqual(0x06050403, parsed.quad_val)
151 self.assertEqual(0x0e0d0c0b0a090807, parsed.oct_val)
153 self.assertEqual(0x9988, parsed.other_random.another_double)
154 self.assertEqual(bytes.fromhex("00112233445566778899"),
155 parsed.other_random.single_arr)
156 self.assertEqual(0xd4d3d2d1, parsed.other_random.another_quad)
158 self.assertEqual(bytes.fromhex("aabb"), parsed.yet_other_random.arr_one)
159 self.assertEqual(bytes.fromhex("ccddee"), parsed.yet_other_random.arr_two)
161 self.assertEqual({
162 "single_val": 0x99,
163 "double_val": 0x0201,
164 "quad_val": 0x06050403,
165 "oct_val": 0x0e0d0c0b0a090807,
166 "other_random": {
167 "another_double": 0x9988,
168 "single_arr": "00112233445566778899",
169 "another_quad": 0xd4d3d2d1,
170 },
171 "yet_other_random": {
172 "arr_one": "aabb",
173 "arr_two": "ccddee",
174 }
175 }, parsed.to_dict())
177 def test_parsing_big(self):
178 parsed = RandomStruct(self.packed, little=False)
180 self.assertEqual(0x99, parsed.single_val)
181 self.assertEqual(0x0102, parsed.double_val)
182 self.assertEqual(0x03040506, parsed.quad_val)
183 self.assertEqual(0x0708090a0b0c0d0e, parsed.oct_val)
185 self.assertEqual(0x8899, parsed.other_random.another_double)
186 self.assertEqual(bytes.fromhex("00112233445566778899"),
187 parsed.other_random.single_arr)
188 self.assertEqual(0xd1d2d3d4, parsed.other_random.another_quad)
190 self.assertEqual(bytes.fromhex("aabb"), parsed.yet_other_random.arr_one)
191 self.assertEqual(bytes.fromhex("ccddee"), parsed.yet_other_random.arr_two)
193 self.assertEqual({
194 "single_val": 0x99,
195 "double_val": 0x0102,
196 "quad_val": 0x03040506,
197 "oct_val": 0x0708090a0b0c0d0e,
198 "other_random": {
199 "another_double": 0x8899,
200 "single_arr": "00112233445566778899",
201 "another_quad": 0xd1d2d3d4,
202 },
203 "yet_other_random": {
204 "arr_one": "aabb",
205 "arr_two": "ccddee",
206 }
207 }, parsed.to_dict())
209 def test_parsing_toosmall(self):
210 with self.assertRaises(ValueError):
211 RandomStruct(b"thisistoosmall")
213 @parameterized.expand([
214 ("invalid_one", Invalid1),
215 ("invalid_two", Invalid2),
216 ("valid_with_invalid", ValidWithInvalid)
217 ])
218 def test_invalid_spec(self, _, kls):
219 with self.assertRaises(ValueError):
220 kls.get_bytelength()
222 with self.assertRaises(ValueError):
223 kls(b'somethingtoparse')