trxcon/l1sched: clarify TDMA Fn (mod 26) maps
[osmocom-bb.git] / src / target / trx_toolkit / test_data_msg.py
blobec6c2ec1d2a799a0b14a2ceb972fc2ec2f617cdd
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
4 # TRX Toolkit
5 # Unit test for TRXD message codec
7 # (C) 2019 by Vadim Yanitskiy <axilirator@gmail.com>
9 # All Rights Reserved
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2 of the License, or
14 # (at your option) any later version.
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 import unittest
23 from data_msg import Msg, TxMsg, RxMsg
25 class Msg_Test(unittest.TestCase):
26 # Compare message a with message b
27 def _compare_msg(self, a, b):
28 # Make sure we're comparing messages of the same type
29 self.assertEqual(a.__class__, b.__class__)
31 # Compare common header fields
32 self.assertEqual(a.ver, b.ver)
33 self.assertEqual(a.fn, b.fn)
34 self.assertEqual(a.tn, b.tn)
36 # Burst bits (if present)
37 self.assertEqual(a.burst, b.burst)
39 # TxMsg specific fields
40 if isinstance(a, TxMsg):
41 self.assertEqual(a.pwr, b.pwr)
43 # RxMsg specific fields
44 if isinstance(a, RxMsg):
45 # Version independent fields
46 self.assertEqual(a.toa256, b.toa256)
47 self.assertEqual(a.rssi, b.rssi)
49 # Version specific fields
50 if a.ver >= 1:
51 self.assertEqual(a.nope_ind, b.nope_ind)
52 self.assertEqual(a.mod_type, b.mod_type)
53 self.assertEqual(a.tsc_set, b.tsc_set)
54 self.assertEqual(a.tsc, b.tsc)
55 self.assertEqual(a.ci, b.ci)
57 # Make sure that message validation throws a ValueError
58 def test_validate(self):
59 # Unknown version
60 with self.assertRaises(ValueError):
61 msg = RxMsg(fn = 0, tn = 0, ver = 100)
62 msg.validate()
64 # Uninitialized field
65 with self.assertRaises(ValueError):
66 msg = RxMsg()
67 msg.validate()
68 with self.assertRaises(ValueError):
69 msg = RxMsg(fn = None, tn = 0)
70 msg.validate()
72 # Out-of-range value(s)
73 with self.assertRaises(ValueError):
74 msg = RxMsg(fn = -1, tn = 0)
75 msg.validate()
76 with self.assertRaises(ValueError):
77 msg = RxMsg(fn = 0, tn = 10)
78 msg.validate()
80 # Validate header and burst randomization
81 def test_rand_hdr_burst(self):
82 tx_msg = TxMsg()
83 rx_msg = RxMsg()
85 for i in range(100):
86 tx_msg.rand_burst()
87 rx_msg.rand_burst()
88 tx_msg.rand_hdr()
89 rx_msg.rand_hdr()
91 tx_msg.validate()
92 rx_msg.validate()
94 def _test_enc_dec(self, msg, legacy = False, nope_ind = False):
95 # Prepare a given message (randomize)
96 msg.rand_hdr()
98 # NOPE.ind contains no burst
99 if not nope_ind:
100 msg.rand_burst()
101 else:
102 msg.nope_ind = True
103 msg.mod_type = None
104 msg.tsc_set = None
105 msg.tsc = None
107 # Encode a given message to bytes
108 msg_enc = msg.gen_msg(legacy)
110 # Decode a new message from bytes
111 msg_dec = msg.__class__()
112 msg_dec.parse_msg(msg_enc)
114 # Compare decoded vs the original
115 self._compare_msg(msg, msg_dec)
117 # Validate encoding and decoding
118 def test_enc_dec(self):
119 for ver in Msg.KNOWN_VERSIONS:
120 with self.subTest("TxMsg", ver = ver):
121 msg = TxMsg(ver = ver)
122 self._test_enc_dec(msg)
124 with self.subTest("RxMsg", ver = ver):
125 msg = RxMsg(ver = ver)
126 self._test_enc_dec(msg)
128 if ver >= 1:
129 with self.subTest("RxMsg NOPE.ind", ver = ver):
130 msg = RxMsg(ver = ver)
131 self._test_enc_dec(msg, nope_ind = True)
133 with self.subTest("RxMsg (legacy transceiver)"):
134 msg = RxMsg(ver = 0)
135 self._test_enc_dec(msg, legacy = True)
137 # Validate bit conversations
138 def test_bit_conv(self):
139 usbits_ref = list(range(0, 256))
140 sbits_ref = list(range(-127, 128))
142 # Test both usbit2sbit() and sbit2usbit()
143 sbits = Msg.usbit2sbit(usbits_ref)
144 usbits = Msg.sbit2usbit(sbits)
145 self.assertEqual(usbits[:255], usbits_ref[:255])
146 self.assertEqual(usbits[255], 254)
148 # Test both sbit2ubit() and ubit2sbit()
149 ubits = Msg.sbit2ubit(sbits_ref)
150 self.assertEqual(ubits, ([1] * 127 + [0] * 128))
152 sbits = Msg.ubit2sbit(ubits)
153 self.assertEqual(sbits, ([-127] * 127 + [127] * 128))
155 def _test_transform(self, msg):
156 # Prepare given messages
157 msg.rand_hdr()
158 msg.rand_burst()
160 # Perform message transformation
161 if isinstance(msg, TxMsg):
162 msg_trans = msg.trans()
163 else:
164 msg_trans = msg.trans()
166 self.assertEqual(msg_trans.ver, msg.ver)
167 self.assertEqual(msg_trans.fn, msg.fn)
168 self.assertEqual(msg_trans.tn, msg.tn)
170 if isinstance(msg, RxMsg):
171 burst = Msg.sbit2ubit(msg.burst)
172 self.assertEqual(msg_trans.burst, burst)
173 else:
174 burst = Msg.ubit2sbit(msg.burst)
175 self.assertEqual(msg_trans.burst, burst)
177 # Validate message transformation
178 def test_transform(self):
179 for ver in Msg.KNOWN_VERSIONS:
180 with self.subTest("TxMsg", ver = ver):
181 msg = TxMsg(ver = ver)
182 self._test_transform(msg)
184 with self.subTest("RxMsg", ver = ver):
185 msg = RxMsg(ver = ver)
186 self._test_transform(msg)
188 if __name__ == '__main__':
189 unittest.main()