Completed
Pull Request — master (#35)
by
unknown
07:26
created

TestStarStruct.test_no_error_message()   B

Complexity

Conditions 3

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
c 1
b 0
f 0
dl 0
loc 26
rs 8.8571
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_2(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', crc32, [b'data']),
38
        ])
39
40
        test_data = {
41
            'data': {
42
                'length_in_objects': 2,
43
                'vardata': [
44
                    {'x': 1, 'y': 2},
45
                    {'x': 3, 'y': 4},
46
                ],
47
            },
48
        }
49
50
        made = CRCedMessage.make(test_data)
51
        # assert len(made) == 5
52
        assert len(made.data.vardata) == 2
53
        assert made.data.vardata[0].x == 1
54
        assert made.data.vardata[0].y == 2
55
        assert made.function_data == crc32(TestStruct.pack(test_data['data']))
56
57
    def test_one_element(self):
58
        def crc32_wrapper(*args):
59
            return crc32(b''.join(args))
60
61
        CompareMessage = Message('CompareMessage', [
62
            ('length_in_objects', 'H', 'vardata'),
63
            ('vardata', self.VarTest, 'length_in_objects'),
64
        ])
65
66
        CRCedMessage = Message('TestStruct', [
67
            ('length_in_objects', 'H', 'vardata'),
68
            ('vardata', self.VarTest, 'length_in_objects'),
69
            ('function_data', 'I', crc32_wrapper, [b'length_in_objects', b'vardata']),
70
        ])
71
72
        test_data = {
73
            'length_in_objects': 2,
74
            'vardata': [
75
                {'x': 1, 'y': 2},
76
                {'x': 3, 'y': 4},
77
            ],
78
        }
79
80
        made = CRCedMessage.make(test_data)
81
        # assert len(made) == 5
82
        assert len(made.vardata) == 2
83
        assert made.vardata[0].x == 1
84
        assert made.vardata[0].y == 2
85
86
        assert made.function_data == crc32(CompareMessage.pack(test_data))
87
88
    def test_adding_element(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
89
        def adder(x, y):
90
            return x + y
91
92
        AdderMessage = Message('AdderMessage', [
93
            ('item_a', 'H'),
94
            ('item_b', 'B'),
95
            ('function_data', 'I', adder, ['item_a', 'item_b']),
96
        ])
97
98
        test_data = {
99
            'item_a': 2,
100
            'item_b': 5,
101
        }
102
103
        made = AdderMessage.make(test_data)
104
        assert made.item_a == 2
105
        assert made.item_b == 5
106
107
        assert made.function_data == 7
108
109
    def test_adding_element_list(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
110
        def adder(*args):
111
            return sum(args)
112
113
        AdderMessage = Message('AdderMessage', [
114
            ('item_a', 'H'),
115
            ('item_b', 'B'),
116
            ('item_c', 'B'),
117
            ('item_d', 'B'),
118
            ('item_e', 'B'),
119
            # Note, there is no item 'e' in the list of arguments
120
            ('function_data', 'I', adder, ['item_a', 'item_b', 'item_c', 'item_d']),
121
        ])
122
123
        # Test getting the correct result
124
        test_data = {
125
            'item_a': 2,
126
            'item_b': 5,
127
            'item_c': 7,
128
            'item_d': 4,
129
            'item_e': 6,
130
        }
131
132
        made = AdderMessage.make(test_data)
133
        assert made.item_a == 2
134
        assert made.item_b == 5
135
136
        assert made.function_data == 2 + 5 + 7 + 4
137
138
        # Check packing and unpacking
139
        packed = AdderMessage.pack(test_data)
140
        assert packed == b'\x02\x00\x05\x07\x04\x06\x12\x00\x00\x00'
141
        assert packed == made.pack()
142
143
        unpacked = AdderMessage.unpack(packed)
144
        assert made == unpacked
145
146
        # Test with correct result
147
        test_data_2 = {
148
            'item_a': 2,
149
            'item_b': 5,
150
            'item_c': 7,
151
            'item_d': 4,
152
            'item_e': 6,
153
            'function_data': 2 + 5 + 7 + 4,
154
        }
155
        made = AdderMessage.make(test_data_2)
156
        assert made.item_a == 2
157
        assert made.item_b == 5
158
159
        assert made.function_data == 2 + 5 + 7 + 4
160
161
        # Test with incorrect result
162
        test_data_2 = {
163
            'item_a': 2,
164
            'item_b': 5,
165
            'item_c': 7,
166
            'item_d': 4,
167
            'item_e': 6,
168
            'function_data': -1,
169
        }
170
171
        with pytest.raises(ValueError):
172
            made = AdderMessage.make(test_data_2)
173
174
    def test_no_error_message(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
175
        def adder(*args):
176
            return sum(args)
177
178
        AdderMessage = Message('AdderMessage', [
179
            ('item_a', 'H'),
180
            ('item_b', 'B'),
181
            ('item_c', 'B'),
182
            ('item_d', 'B'),
183
            ('item_e', 'B'),
184
            # Note, there is no item 'e' in the list of arguments
185
            ('function_data', 'I', adder, ['item_a', 'item_b', 'item_c', 'item_d'], False),
186
        ])
187
188
        # Test with incorrect result
189
        test_data_2 = {
190
            'item_a': 2,
191
            'item_b': 5,
192
            'item_c': 7,
193
            'item_d': 4,
194
            'item_e': 6,
195
            'function_data': -1,
196
        }
197
198
        made = AdderMessage.make(test_data_2)
199
        assert made.function_data == -1
200