1 | #!/usr/bin/env python3 |
||
2 | |||
3 | """Tests for the starstruct class""" |
||
4 | |||
5 | import struct |
||
6 | import unittest |
||
7 | from hashlib import md5 |
||
8 | |||
9 | from starstruct.message import Message |
||
10 | |||
11 | |||
12 | class TestStarStructNone(unittest.TestCase): |
||
13 | """StarStruct module tests""" |
||
14 | # TODO: Clean up these tests, change names, and move a bunch of the items to a helper function |
||
15 | |||
16 | VarTest = Message('VarTest', [ |
||
17 | ('x', 'B'), |
||
18 | ('y', 'B'), |
||
19 | ]) |
||
20 | |||
21 | def test_single_element_1(self): |
||
22 | def pseudo_salted_md5(salt, original): |
||
23 | temp_md5 = md5(original) |
||
24 | |||
25 | if salt is None: |
||
26 | salt = b'' |
||
27 | |||
28 | return md5(salt + temp_md5.digest()).digest() |
||
29 | |||
30 | def pack_salt(data): |
||
31 | return b''.join(item.to_bytes(1, 'little') for item in data) |
||
32 | |||
33 | TestStruct = Message('TestStruct', [ |
||
34 | ('length_in_objects', 'H', 'vardata'), |
||
35 | ('vardata', self.VarTest, 'length_in_objects'), |
||
36 | ]) |
||
37 | |||
38 | CRCedMessage = Message('CRCedMessage', [ |
||
39 | ('data', TestStruct), |
||
40 | ('salted', None), |
||
41 | ('function_data', '16B', { |
||
42 | 'make': (pseudo_salted_md5, 'salted', b'data'), |
||
43 | 'pack': (pseudo_salted_md5, 'salted', b'data'), |
||
44 | 'unpack': (pack_salt, 'function_data'), |
||
45 | }, False), |
||
46 | ]) |
||
47 | |||
48 | test_data = { |
||
49 | 'data': { |
||
50 | 'length_in_objects': 2, |
||
51 | 'vardata': [ |
||
52 | {'x': 1, 'y': 2}, |
||
53 | {'x': 3, 'y': 4}, |
||
54 | ], |
||
55 | }, |
||
56 | 'salted': b'random_salter', |
||
57 | } |
||
58 | |||
59 | made = CRCedMessage.make(test_data) |
||
60 | assert len(made.data.vardata) == 2 |
||
61 | assert made.data.vardata[0].x == 1 |
||
62 | assert made.data.vardata[0].y == 2 |
||
63 | |||
64 | no_data = made.pack() |
||
65 | regular = CRCedMessage.pack(**test_data) |
||
0 ignored issues
–
show
|
|||
66 | assert regular == no_data |
||
67 | |||
68 | # Show that there's no room to have the random salter be packed |
||
69 | len_data = len(no_data) - 16 |
||
70 | assert no_data[0:len_data] == struct.pack('HBBBB', 2, 1, 2, 3, 4) |
||
71 | assert md5( |
||
72 | b'random_salter' + |
||
73 | md5(no_data[0:len_data]).digest() |
||
74 | ).digest() == no_data[len_data:] |
||
75 | |||
76 | unpacked = CRCedMessage.unpack(no_data) |
||
77 | |||
78 | assert unpacked.salted is None |
||
79 | assert unpacked.function_data == made.function_data |
||
80 | |||
81 | # TEMP |
||
82 | new = unpacked._replace(**{'salted': b'random_salter'}) |
||
0 ignored issues
–
show
Usage of
* or ** arguments should usually be done with care.
Generally, there is nothing wrong with usage of For more information, we can recommend this blog post from Ned Batchelder including its comments which also touches this aspect. ![]() |
|||
83 | assert new.salted == b'random_salter' |
||
84 | # print(new._asdict()) |
||
85 | |||
86 | View Code Duplication | def test_single_element_2(self): |
|
0 ignored issues
–
show
|
|||
87 | def pseudo_salted_md5(salt, original): |
||
88 | temp_md5 = md5(original) |
||
89 | |||
90 | if salt is None: |
||
91 | salt = b'' |
||
92 | |||
93 | return md5(salt + temp_md5.digest()).digest() |
||
94 | |||
95 | def do_nothing(data): |
||
96 | return data |
||
97 | |||
98 | TestStruct = Message('TestStruct', [ |
||
99 | ('length_in_objects', 'H', 'vardata'), |
||
100 | ('vardata', self.VarTest, 'length_in_objects'), |
||
101 | ]) |
||
102 | |||
103 | CRCedMessage = Message('CRCedMessage', [ |
||
104 | ('data', TestStruct), |
||
105 | ('salted', None), |
||
106 | ('function_data', '16B', { |
||
107 | 'make': (pseudo_salted_md5, 'salted', b'data'), |
||
108 | 'pack': (pseudo_salted_md5, 'salted', b'data'), |
||
109 | 'unpack': (do_nothing, 'function_data'), |
||
110 | }, False), |
||
111 | ]) |
||
112 | |||
113 | test_data = { |
||
114 | 'data': { |
||
115 | 'length_in_objects': 2, |
||
116 | 'vardata': [ |
||
117 | {'x': 1, 'y': 2}, |
||
118 | {'x': 3, 'y': 4}, |
||
119 | ], |
||
120 | }, |
||
121 | 'salted': b'random_salter', |
||
122 | } |
||
123 | |||
124 | made = CRCedMessage.make(test_data) |
||
125 | assert len(made.data.vardata) == 2 |
||
126 | assert made.data.vardata[0].x == 1 |
||
127 | assert made.data.vardata[0].y == 2 |
||
128 | |||
129 | no_data = made.pack() |
||
130 | regular = CRCedMessage.pack(**test_data) |
||
0 ignored issues
–
show
Usage of
* or ** arguments should usually be done with care.
Generally, there is nothing wrong with usage of For more information, we can recommend this blog post from Ned Batchelder including its comments which also touches this aspect. ![]() |
|||
131 | assert regular == no_data |
||
132 | |||
133 | # Show that there's no room to have the random salter be packed |
||
134 | len_data = len(no_data) - 16 |
||
135 | assert no_data[0:len_data] == struct.pack('HBBBB', 2, 1, 2, 3, 4) |
||
136 | assert md5( |
||
137 | b'random_salter' + |
||
138 | md5(no_data[0:len_data]).digest() |
||
139 | ).digest() == no_data[len_data:] |
||
140 | |||
141 | unpacked = CRCedMessage.unpack(no_data) |
||
142 | |||
143 | assert unpacked.salted is None |
||
144 | # This is non symmetric for this test, so we can't just check based on the made item |
||
145 | assert unpacked.function_data == (157, 38, 247, 245, 5, 71, 43, 227, 80, 44, 10, 243, 48, 248, 163, 207) |
||
146 | |||
147 | # TEMP |
||
148 | new = unpacked._replace(**{'salted': b'random_salter'}) |
||
0 ignored issues
–
show
Usage of
* or ** arguments should usually be done with care.
Generally, there is nothing wrong with usage of For more information, we can recommend this blog post from Ned Batchelder including its comments which also touches this aspect. ![]() |
|||
149 | assert new.salted == b'random_salter' |
||
150 | # print(new._asdict()) |
||
151 | |||
152 | View Code Duplication | def test_single_element_3(self): |
|
0 ignored issues
–
show
|
|||
153 | def pseudo_salted_md5(salt, original): |
||
154 | temp_md5 = md5(original) |
||
155 | |||
156 | if salt is None: |
||
157 | salt = b'' |
||
158 | |||
159 | return md5(salt + temp_md5.digest()).digest() |
||
160 | |||
161 | def double(data): |
||
162 | return [item * 2 for item in data] |
||
163 | |||
164 | TestStruct = Message('TestStruct', [ |
||
165 | ('length_in_objects', 'H', 'vardata'), |
||
166 | ('vardata', self.VarTest, 'length_in_objects'), |
||
167 | ]) |
||
168 | |||
169 | CRCedMessage = Message('CRCedMessage', [ |
||
170 | ('data', TestStruct), |
||
171 | ('salted', None), |
||
172 | ('function_data', '16B', { |
||
173 | 'make': (pseudo_salted_md5, 'salted', b'data'), |
||
174 | 'pack': (pseudo_salted_md5, 'salted', b'data'), |
||
175 | 'unpack': (double, 'function_data'), |
||
176 | }, False), |
||
177 | ]) |
||
178 | |||
179 | test_data = { |
||
180 | 'data': { |
||
181 | 'length_in_objects': 2, |
||
182 | 'vardata': [ |
||
183 | {'x': 1, 'y': 2}, |
||
184 | {'x': 3, 'y': 4}, |
||
185 | ], |
||
186 | }, |
||
187 | 'salted': b'random_salter', |
||
188 | } |
||
189 | |||
190 | made = CRCedMessage.make(test_data) |
||
191 | assert len(made.data.vardata) == 2 |
||
192 | assert made.data.vardata[0].x == 1 |
||
193 | assert made.data.vardata[0].y == 2 |
||
194 | |||
195 | no_data = made.pack() |
||
196 | regular = CRCedMessage.pack(**test_data) |
||
0 ignored issues
–
show
Usage of
* or ** arguments should usually be done with care.
Generally, there is nothing wrong with usage of For more information, we can recommend this blog post from Ned Batchelder including its comments which also touches this aspect. ![]() |
|||
197 | assert regular == no_data |
||
198 | |||
199 | # Show that there's no room to have the random salter be packed |
||
200 | len_data = len(no_data) - 16 |
||
201 | assert no_data[0:len_data] == struct.pack('HBBBB', 2, 1, 2, 3, 4) |
||
202 | assert md5( |
||
203 | b'random_salter' + |
||
204 | md5(no_data[0:len_data]).digest() |
||
205 | ).digest() == no_data[len_data:] |
||
206 | |||
207 | unpacked = CRCedMessage.unpack(no_data) |
||
208 | |||
209 | assert unpacked.salted is None |
||
210 | # This is non symmetric for this test, so we can't just check based on the made item |
||
211 | assert unpacked.function_data == [314, 76, 494, 490, 10, 142, 86, 454, 160, 88, 20, 486, 96, 496, 326, 414] |
||
212 | |||
213 | View Code Duplication | def test_single_element_4(self): |
|
0 ignored issues
–
show
|
|||
214 | def pseudo_salted_md5(salt, original): |
||
215 | temp_md5 = md5(original) |
||
216 | |||
217 | if salt is None: |
||
218 | salt = b'' |
||
219 | |||
220 | return md5(salt + temp_md5.digest()).digest() |
||
221 | |||
222 | def double(data): |
||
223 | return [item * 2 for item in data] |
||
224 | |||
225 | TestStruct = Message('TestStruct', [ |
||
226 | ('length_in_objects', 'H', 'vardata'), |
||
227 | ('vardata', self.VarTest, 'length_in_objects'), |
||
228 | ]) |
||
229 | |||
230 | # This one has nothing to do with the original packed message |
||
231 | CRCedMessage = Message('CRCedMessage', [ |
||
232 | ('data', TestStruct), |
||
233 | ('salted', None), |
||
234 | ('function_data', '16B', { |
||
235 | 'make': (pseudo_salted_md5, 'salted', b'data'), |
||
236 | 'pack': (pseudo_salted_md5, 'salted', b'data'), |
||
237 | 'unpack': (double, b'data'), |
||
238 | }, False), |
||
239 | ]) |
||
240 | |||
241 | test_data = { |
||
242 | 'data': { |
||
243 | 'length_in_objects': 2, |
||
244 | 'vardata': [ |
||
245 | {'x': 1, 'y': 2}, |
||
246 | {'x': 3, 'y': 4}, |
||
247 | ], |
||
248 | }, |
||
249 | 'salted': b'random_salter', |
||
250 | } |
||
251 | |||
252 | made = CRCedMessage.make(test_data) |
||
253 | assert len(made.data.vardata) == 2 |
||
254 | assert made.data.vardata[0].x == 1 |
||
255 | assert made.data.vardata[0].y == 2 |
||
256 | |||
257 | no_data = made.pack() |
||
258 | regular = CRCedMessage.pack(**test_data) |
||
0 ignored issues
–
show
Usage of
* or ** arguments should usually be done with care.
Generally, there is nothing wrong with usage of For more information, we can recommend this blog post from Ned Batchelder including its comments which also touches this aspect. ![]() |
|||
259 | assert regular == no_data |
||
260 | |||
261 | # Show that there's no room to have the random salter be packed |
||
262 | len_data = len(no_data) - 16 |
||
263 | assert no_data[0:len_data] == struct.pack('HBBBB', 2, 1, 2, 3, 4) |
||
264 | assert md5( |
||
265 | b'random_salter' + |
||
266 | md5(no_data[0:len_data]).digest() |
||
267 | ).digest() == no_data[len_data:] |
||
268 | |||
269 | unpacked = CRCedMessage.unpack(no_data) |
||
270 | |||
271 | assert unpacked.salted is None |
||
272 | # This is non symmetric for this test, so we can't just check based on the made item |
||
273 | assert unpacked.function_data == [4, 0, 2, 4, 6, 8] |
||
274 | |||
275 | def test_nounpack_function(self): |
||
276 | def pseudo_salted_md5(salt, original): |
||
277 | temp_md5 = md5(original) |
||
278 | |||
279 | if salt is None: |
||
280 | salt = b'' |
||
281 | |||
282 | return md5(salt + temp_md5.digest()).digest() |
||
283 | |||
284 | TestStruct = Message('TestStruct', [ |
||
285 | ('length_in_objects', 'H', 'vardata'), |
||
286 | ('vardata', self.VarTest, 'length_in_objects'), |
||
287 | ]) |
||
288 | |||
289 | # This one has nothing to do with the original packed message |
||
290 | ExplicitNone = Message('Explicit', [ |
||
291 | ('data', TestStruct), |
||
292 | ('salted', None), |
||
293 | ('function_data', '16B', { |
||
294 | 'make': (pseudo_salted_md5, 'salted', b'data'), |
||
295 | 'pack': (pseudo_salted_md5, 'salted', b'data'), |
||
296 | 'unpack': (None, ), |
||
297 | }, False), |
||
298 | ]) |
||
299 | |||
300 | ImplicitNone = Message('Implicit', [ |
||
301 | ('data', TestStruct), |
||
302 | ('salted', None), |
||
303 | ('function_data', '16B', { |
||
304 | 'make': (pseudo_salted_md5, 'salted', b'data'), |
||
305 | 'pack': (pseudo_salted_md5, 'salted', b'data'), |
||
306 | }, False), |
||
307 | ]) |
||
308 | |||
309 | test_data = { |
||
310 | 'data': { |
||
311 | 'length_in_objects': 2, |
||
312 | 'vardata': [ |
||
313 | {'x': 1, 'y': 2}, |
||
314 | {'x': 3, 'y': 4}, |
||
315 | ], |
||
316 | }, |
||
317 | 'salted': b'random_salter', |
||
318 | } |
||
319 | |||
320 | made = ExplicitNone.make(test_data) |
||
321 | assert len(made.data.vardata) == 2 |
||
322 | assert made.data.vardata[0].x == 1 |
||
323 | assert made.data.vardata[0].y == 2 |
||
324 | |||
325 | no_data = made.pack() |
||
326 | regular = ExplicitNone.pack(**test_data) |
||
0 ignored issues
–
show
Usage of
* or ** arguments should usually be done with care.
Generally, there is nothing wrong with usage of For more information, we can recommend this blog post from Ned Batchelder including its comments which also touches this aspect. ![]() |
|||
327 | assert regular == no_data |
||
328 | |||
329 | # Show that there's no room to have the random salter be packed |
||
330 | len_data = len(no_data) - 16 |
||
331 | assert no_data[0:len_data] == struct.pack('HBBBB', 2, 1, 2, 3, 4) |
||
332 | assert md5( |
||
333 | b'random_salter' + |
||
334 | md5(no_data[0:len_data]).digest() |
||
335 | ).digest() == no_data[len_data:] |
||
336 | |||
337 | unpacked = ExplicitNone.unpack(no_data) |
||
338 | |||
339 | assert unpacked.salted is None |
||
340 | assert unpacked.function_data == (157, 38, 247, 245, 5, 71, 43, 227, 80, 44, 10, 243, 48, 248, 163, 207) |
||
341 | |||
342 | made = ImplicitNone.make(test_data) |
||
343 | assert len(made.data.vardata) == 2 |
||
344 | assert made.data.vardata[0].x == 1 |
||
345 | assert made.data.vardata[0].y == 2 |
||
346 | |||
347 | no_data = made.pack() |
||
348 | regular = ImplicitNone.pack(**test_data) |
||
0 ignored issues
–
show
Usage of
* or ** arguments should usually be done with care.
Generally, there is nothing wrong with usage of For more information, we can recommend this blog post from Ned Batchelder including its comments which also touches this aspect. ![]() |
|||
349 | assert regular == no_data |
||
350 | |||
351 | # Show that there's no room to have the random salter be packed |
||
352 | len_data = len(no_data) - 16 |
||
353 | assert no_data[0:len_data] == struct.pack('HBBBB', 2, 1, 2, 3, 4) |
||
354 | assert md5( |
||
355 | b'random_salter' + |
||
356 | md5(no_data[0:len_data]).digest() |
||
357 | ).digest() == no_data[len_data:] |
||
358 | |||
359 | unpacked = ImplicitNone.unpack(no_data) |
||
360 | |||
361 | assert unpacked.salted is None |
||
362 | assert unpacked.function_data == (157, 38, 247, 245, 5, 71, 43, 227, 80, 44, 10, 243, 48, 248, 163, 207) |
||
363 |
Generally, there is nothing wrong with usage of
*
or**
arguments. For readability of the code base, we suggest to not over-use these language constructs though.For more information, we can recommend this blog post from Ned Batchelder including its comments which also touches this aspect.