TestStarStruct.test_verifying_unpack()   F
last analyzed

Complexity

Conditions 16

Size

Total Lines 86

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 16
c 1
b 0
f 0
dl 0
loc 86
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like TestStarStruct.test_verifying_unpack() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#!/usr/bin/env python3
2
3
"""Tests for the starstruct class"""
4
5
# import struct
6
import unittest
7
from binascii import crc32
8
9
import pytest
10
11
from starstruct.message import Message
12
# from starstruct.modes import Mode
13
14
15
# pylint: disable=line-too-long,invalid-name
16
class TestStarStruct(unittest.TestCase):
17
    """StarStruct module tests"""
18
19
    VarTest = Message('VarTest', [
20
        ('x', 'B'),
21
        ('y', 'B'),
22
    ])
23
24
    Repeated = Message('Repeated', [
25
        ('x', 'B'),
26
        ('z', 'H'),
27
    ])
28
29
    def test_single_element_with_set(self):
30
        TestStruct = Message('TestStruct', [
31
            ('length_in_objects', 'H', 'vardata'),
32
            ('vardata', self.VarTest, 'length_in_objects'),
33
        ])
34
35
        CRCedMessage = Message('CRCedMessage', [
36
            ('data', TestStruct),
37
            ('function_data', 'I', {
38
                (crc32, b'data')
39
            }),
40
        ])
41
42
        test_data = {
43
            'data': {
44
                'length_in_objects': 2,
45
                'vardata': [
46
                    {'x': 1, 'y': 2},
47
                    {'x': 3, 'y': 4},
48
                ],
49
            },
50
        }
51
52
        made = CRCedMessage.make(test_data)
53
        # assert len(made) == 5
54
        assert len(made.data.vardata) == 2
55
        assert made.data.vardata[0].x == 1
56
        assert made.data.vardata[0].y == 2
57
        assert made.function_data == crc32(TestStruct.pack(test_data['data']))
58
59
    def test_single_element_2(self):
60
        TestStruct = Message('TestStruct', [
61
            ('length_in_objects', 'H', 'vardata'),
62
            ('vardata', self.VarTest, 'length_in_objects'),
63
        ])
64
65
        CRCedMessage = Message('CRCedMessage', [
66
            ('data', TestStruct),
67
            ('function_data', 'I', {
68
                'pack': (crc32, b'data'),
69
                'make': (crc32, b'data'),
70
                'unpack': (crc32, b'data'),
71
            }),
72
        ])
73
74
        test_data = {
75
            'data': {
76
                'length_in_objects': 2,
77
                'vardata': [
78
                    {'x': 1, 'y': 2},
79
                    {'x': 3, 'y': 4},
80
                ],
81
            },
82
        }
83
84
        made = CRCedMessage.make(test_data)
85
        # assert len(made) == 5
86
        assert len(made.data.vardata) == 2
87
        assert made.data.vardata[0].x == 1
88
        assert made.data.vardata[0].y == 2
89
        assert made.function_data == crc32(TestStruct.pack(test_data['data']))
90
91
    def test_one_element(self):
92
        def crc32_wrapper(*args):
93
            return crc32(b''.join(args))
94
95
        CompareMessage = Message('CompareMessage', [
96
            ('length_in_objects', 'H', 'vardata'),
97
            ('vardata', self.VarTest, 'length_in_objects'),
98
        ])
99
100
        CRCedMessage = Message('TestStruct', [
101
            ('length_in_objects', 'H', 'vardata'),
102
            ('vardata', self.VarTest, 'length_in_objects'),
103
            ('function_data', 'I', {
104
                (crc32_wrapper, b'length_in_objects', b'vardata')
105
            }),
106
        ])
107
108
        test_data = {
109
            'length_in_objects': 2,
110
            'vardata': [
111
                {'x': 1, 'y': 2},
112
                {'x': 3, 'y': 4},
113
            ],
114
        }
115
116
        made = CRCedMessage.make(test_data)
117
        # assert len(made) == 5
118
        assert len(made.vardata) == 2
119
        assert made.vardata[0].x == 1
120
        assert made.vardata[0].y == 2
121
122
        assert made.function_data == crc32(CompareMessage.pack(test_data))
123
124
    def test_adding_element(self):
125
        def adder(x, y):
126
            return x + y
127
128
        AdderMessage = Message('AdderMessage', [
129
            ('item_a', 'H'),
130
            ('item_b', 'B'),
131
            ('function_data', 'I', {
132
                (adder, 'item_a', 'item_b')
133
            }),
134
        ])
135
136
        test_data = {
137
            'item_a': 2,
138
            'item_b': 5,
139
        }
140
141
        made = AdderMessage.make(test_data)
142
        assert made.item_a == 2
143
        assert made.item_b == 5
144
145
        assert made.function_data == 7
146
147
    def test_adding_element_list(self):
148
        def adder(*args):
149
            return sum(args)
150
151
        AdderMessage = Message('AdderMessage', [
152
            ('item_a', 'H'),
153
            ('item_b', 'B'),
154
            ('item_c', 'B'),
155
            ('item_d', 'B'),
156
            ('item_e', 'B'),
157
            # Note, there is no item 'e' in the list of arguments
158
            ('function_data', 'I', {
159
                (adder, 'item_a', 'item_b', 'item_c', 'item_d')
160
            }),
161
        ])
162
163
        # Test getting the correct result
164
        test_data = {
165
            'item_a': 2,
166
            'item_b': 5,
167
            'item_c': 7,
168
            'item_d': 4,
169
            'item_e': 6,
170
        }
171
172
        made = AdderMessage.make(test_data)
173
        assert made.item_a == 2
174
        assert made.item_b == 5
175
176
        assert made.function_data == 2 + 5 + 7 + 4
177
178
        # Check packing and unpacking
179
        packed = AdderMessage.pack(test_data)
180
        assert packed == b'\x02\x00\x05\x07\x04\x06\x12\x00\x00\x00'
181
        assert packed == made.pack()
182
183
        unpacked = AdderMessage.unpack(packed)
184
        assert made == unpacked
185
186
        # Test with correct result
187
        test_data_2 = {
188
            'item_a': 2,
189
            'item_b': 5,
190
            'item_c': 7,
191
            'item_d': 4,
192
            'item_e': 6,
193
            'function_data': 2 + 5 + 7 + 4,
194
        }
195
        made = AdderMessage.make(test_data_2)
196
        assert made.item_a == 2
197
        assert made.item_b == 5
198
199
        assert made.function_data == 2 + 5 + 7 + 4
200
201
        # Test with incorrect result
202
        test_data_2 = {
203
            'item_a': 2,
204
            'item_b': 5,
205
            'item_c': 7,
206
            'item_d': 4,
207
            'item_e': 6,
208
            'function_data': -1,
209
        }
210
211
        with pytest.raises(ValueError):
212
            made = AdderMessage.make(test_data_2)
213
214
    def test_no_error_message(self):
215
        def adder(*args):
216
            return sum(args)
217
218
        AdderMessage = Message('AdderMessage', [
219
            ('item_a', 'H'),
220
            ('item_b', 'B'),
221
            ('item_c', 'B'),
222
            ('item_d', 'B'),
223
            ('item_e', 'B'),
224
            # Note, there is no item 'e' in the list of arguments
225
            ('function_data', 'I', {
226
                (adder, 'item_a', 'item_b', 'item_c', 'item_d')
227
            }, False),
228
        ])
229
230
        # Test with incorrect result
231
        test_data_2 = {
232
            'item_a': 2,
233
            'item_b': 5,
234
            'item_c': 7,
235
            'item_d': 4,
236
            'item_e': 6,
237
            'function_data': -1,
238
        }
239
240
        made = AdderMessage.make(test_data_2)
241
        assert made.function_data == -1
242
243
    def test_verifying_unpack(self):
244
        def adder(*args):
245
            return sum(args)
246
247
        AdderMessage = Message('AdderMessage', [
248
            ('item_a', 'H'),
249
            ('item_b', 'B'),
250
            ('item_c', 'B'),
251
            ('item_d', 'B'),
252
            ('item_e', 'B'),
253
            # Note, there is no item 'e' in the list of arguments
254
            ('function_data', 'I', {
255
                (adder, 'item_a', 'item_b', 'item_c', 'item_d')
256
            }),
257
        ])
258
259
        # Test getting the correct result
260
        test_data = {
261
            'item_a': 2,
262
            'item_b': 5,
263
            'item_c': 7,
264
            'item_d': 4,
265
            'item_e': 6,
266
        }
267
268
        made = AdderMessage.make(test_data)
269
        assert made.item_a == 2
270
        assert made.item_b == 5
271
272
        assert made.function_data == 2 + 5 + 7 + 4
273
274
        # Check packing and unpacking
275
        packed = AdderMessage.pack(test_data)
276
        assert packed == b'\x02\x00\x05\x07\x04\x06\x12\x00\x00\x00'
277
        assert packed == made.pack()
278
279
        unpacked = AdderMessage.unpack(packed)
280
        assert made == unpacked
281
282
        # Now we modify the data we are going to unpack, and we should get an error
283
        modified_packed = b'\x02\x00\x05\x07\x04\x06\x11\x11\x11\x11'
284
285
        with pytest.raises(ValueError):
286
            unpacked = AdderMessage.unpack(modified_packed)
287
288
        AdderMessageFalse = Message('AdderMessageFalse', [
289
            ('item_a', 'H'),
290
            ('item_b', 'B'),
291
            ('item_c', 'B'),
292
            ('item_d', 'B'),
293
            ('item_e', 'B'),
294
            # Note, there is no item 'e' in the list of arguments
295
            ('function_data', 'I', {
296
                (adder, 'item_a', 'item_b', 'item_c', 'item_d')
297
            }, False),
298
        ])
299
300
        # Test getting the correct result
301
        test_data = {
302
            'item_a': 2,
303
            'item_b': 5,
304
            'item_c': 7,
305
            'item_d': 4,
306
            'item_e': 6,
307
        }
308
309
        made = AdderMessageFalse.make(test_data)
310
        assert made.item_a == 2
311
        assert made.item_b == 5
312
313
        assert made.function_data == 2 + 5 + 7 + 4
314
315
        # Check packing and unpacking
316
        packed = AdderMessageFalse.pack(test_data)
317
        assert packed == b'\x02\x00\x05\x07\x04\x06\x12\x00\x00\x00'
318
        assert packed == made.pack()
319
320
        unpacked = AdderMessageFalse.unpack(packed)
321
        assert made == unpacked
322
323
        # Now we modify the data we are going to unpack, and we should get an error
324
        modified_packed = b'\x02\x00\x05\x07\x04\x06\x11\x11\x11\x11'
325
326
        # This time it won't fail because we set False for this message
327
        unpacked = AdderMessageFalse.unpack(modified_packed)
328
        assert unpacked.item_a == 2
329