TestElementFixedPointHelpers   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 48
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
c 6
b 0
f 0
dl 0
loc 48
rs 10
wmc 19

7 Methods

Rating   Name   Duplication   Size   Complexity  
A test_invalid_formats() 0 6 3
A test_zero() 0 2 2
A test_basic_example() 0 2 2
A test_valid_formats() 0 3 1
A test_valid_higher_bits() 0 6 1
A test_another_example() 0 4 4
B test_invalid_higher_bits() 0 15 6
1
#!/usr/bin/env python3
2
3
"""Tests for the elementfixedpoint class"""
4
5
import unittest
6
7
from decimal import Decimal
8
9
from starstruct.elementfixedpoint import ElementFixedPoint, get_fixed_bits
10
from starstruct.message import Message
11
from starstruct.modes import Mode
12
13
14
# pylint: disable=no-self-use
15
class TestElementFixedPointHelpers(unittest.TestCase):
16
    """Test the helpers for this class"""
17
    def test_invalid_formats(self):
18
        with self.assertRaises(ValueError):
19
            get_fixed_bits(5, 'Z', 1)
20
21
        with self.assertRaises(ValueError):
22
            get_fixed_bits(8, 'f', 4)
23
24
        # TODO: Make sure that it won't accept more than one number?
25
26
    def test_valid_formats(self):
27
        get_fixed_bits(5, 'h', 1)
28
        get_fixed_bits(15, 'L', 0)
29
30
    def test_invalid_higher_bits(self):
31
        with self.assertRaises(ValueError):
32
            get_fixed_bits(257, 'i', 32)
33
34
        with self.assertRaises(ValueError):
35
            get_fixed_bits(256, 'i', 32)
36
37
        with self.assertRaises(ValueError):
38
            get_fixed_bits('hello', 'i', 3)
39
40
        with self.assertRaises(ValueError):
41
            get_fixed_bits(Decimal('20'), 'h', 17)
42
43
        with self.assertRaises(ValueError):
44
            get_fixed_bits(42, 'i', 33)
45
46
    def test_valid_higher_bits(self):
47
        """Just make sure these all don't fail"""
48
        get_fixed_bits(255, 'I', 8)
49
        get_fixed_bits(15.5, 'I', 4)
50
        get_fixed_bits(22.75, 'i', 11)
51
        get_fixed_bits(Decimal('13.0'), 'q', 16)
52
53
    def test_zero(self):
54
        assert get_fixed_bits(0, 'H', 8) == (0).to_bytes(2, 'big')
55
56
    def test_basic_example(self):
57
        assert get_fixed_bits(Decimal('0.9375'), 'B', 4) == (15).to_bytes(1, 'little')
58
59
    def test_another_example(self):
60
        assert get_fixed_bits(Decimal('12.9375'), 'h', 4) == (192 + 15).to_bytes(2, 'little')
61
        assert get_fixed_bits(Decimal('12.9375'), 'i', 4) == (192 + 15).to_bytes(4, 'little')
62
        assert get_fixed_bits(Decimal('12.9375'), 'q', 4) == (192 + 15).to_bytes(8, 'little')
63
64
65
class TestElementFixedPoint(unittest.TestCase):
66
    """ElementFixedPoint module tests"""
67
68
    def test_valid(self):
69
        """Test field formats that are valid fixedpoint elements."""
70
71
        test_fields = [
72
            ('a', 'F', 'i', 8),
73
            ('b', 'F', 'h', 4),
74
            ('c', 'F', 'h', 7),
75
        ]
76
77
        for field in test_fields:
78
            with self.subTest(field):  # pylint: disable=no-member
79
                out = ElementFixedPoint.valid(field)
80
                self.assertTrue(out)
81
82
    def test_not_valid(self):
83
        """Test field formats that are not valid fixedpoint elements."""
84
85
        test_fields = [
86
            ('a', 'PF', 16, 8),  # Must have numbers preceding the F
87
            ('b', '3D', 8, 8),  # D is not a valid prefix. Must be F for fixedpoint
88
            ('c', 'D', 8.0, 8),  # Must be int, not float
89
            ('d', 'D', 8, 16),  # bytes must be larger than precision.
90
            ('e', 'D', 8),  # Must be of length four
91
        ]
92
93
        for field in test_fields:
94
            with self.subTest(field):  # pylint: disable=no-member
95
                out = ElementFixedPoint.valid(field)
96
                self.assertFalse(out)
97
98
    def test_valid_pack(self):
99
        """Test packing valid fixed point values."""
100
101
        precision = 8
102
        field = ('a', 'F', 'i', precision)
103
        self.assertTrue(ElementFixedPoint.valid(field))
104
        elem = ElementFixedPoint(field, Mode.Big)
105
106
        test_values = [
107
            ({'a': '4'}, 4),
108
            ({'a': 13.5}, 13.5),
109
            ({'a': '13.5'}, '13.5'),
110
            ({'a': '13.500'}, '13.500'),
111
            ({'a': Decimal('13.500')}, '13.500'),
112
            ({'a': 1.1 + 2.2}, '3.3'),
113
        ]
114
115
        multiplier = 2 ** precision
116
        for (in_val, out_val) in test_values:
117
            ret = elem.pack(in_val)
118
119
            if not isinstance(out_val, Decimal):
120
                out_val = Decimal(out_val)
121
122
            self.assertEqual(ret, int((out_val * multiplier)).to_bytes(4, 'big'))
123
124
    def test_valid_make(self):
125
        """Test full packing."""
126
        my_message = Message('my_msg', [
127
            ('my_fixed', 'F', 'i', 8),
128
            ('not_specified_fixed', 'F', 'i', 8),
129
            ('other_fixed', 'F', 'i', 8, 3),
130
            ('just_a_num', 'i'),
131
            ('a_string', '32s'),
132
            ('this_fixed', 'F', 'i', 5),
133
        ], Mode.Big)
134
135
        data = {
136
            'my_fixed': 1.1 + 2.2,
137
            'other_fixed': Decimal('1.1') + Decimal('2.2'),
138
            'not_specified_fixed': Decimal('1.1') + Decimal('2.2'),
139
            'just_a_num': 16,
140
            'a_string': '=====================',
141
            'this_fixed': '1.9375',
142
        }
143
144
        packed = my_message.pack(data)
145
        unpacked = my_message.unpack(packed)
146
147
        assert unpacked.a_string == data['a_string']
148
        assert unpacked.just_a_num == data['just_a_num']
149
        assert unpacked.other_fixed == Decimal('3.3')
150
        assert unpacked.my_fixed == Decimal('3.296875')
151
        assert unpacked.not_specified_fixed == Decimal('3.296875')
152
        assert unpacked.this_fixed == Decimal(data['this_fixed'])
153