#!/usr/bin/env python3 # -*- coding: utf-8 -*- # TRX Toolkit # Unit test for TRXD message codec # # (C) 2019 by Vadim Yanitskiy # # All Rights Reserved # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. import unittest from data_msg import Msg, TxMsg, RxMsg class Msg_Test(unittest.TestCase): # Compare message a with message b def _compare_msg(self, a, b): # Make sure we're comparing messages of the same type self.assertEqual(a.__class__, b.__class__) # Compare common header fields self.assertEqual(a.ver, b.ver) self.assertEqual(a.fn, b.fn) self.assertEqual(a.tn, b.tn) # Burst bits (if present) self.assertEqual(a.burst, b.burst) # TxMsg specific fields if isinstance(a, TxMsg): self.assertEqual(a.pwr, b.pwr) # RxMsg specific fields if isinstance(a, RxMsg): # Version independent fields self.assertEqual(a.toa256, b.toa256) self.assertEqual(a.rssi, b.rssi) # Version specific fields if a.ver >= 1: self.assertEqual(a.nope_ind, b.nope_ind) self.assertEqual(a.mod_type, b.mod_type) self.assertEqual(a.tsc_set, b.tsc_set) self.assertEqual(a.tsc, b.tsc) self.assertEqual(a.ci, b.ci) # Make sure that message validation throws a ValueError def test_validate(self): # Unknown version with self.assertRaises(ValueError): msg = RxMsg(fn = 0, tn = 0, ver = 100) msg.validate() # Uninitialized field with self.assertRaises(ValueError): msg = RxMsg() msg.validate() with self.assertRaises(ValueError): msg = RxMsg(fn = None, tn = 0) msg.validate() # Out-of-range value(s) with self.assertRaises(ValueError): msg = RxMsg(fn = -1, tn = 0) msg.validate() with self.assertRaises(ValueError): msg = RxMsg(fn = 0, tn = 10) msg.validate() # Validate header and burst randomization def test_rand_hdr_burst(self): tx_msg = TxMsg() rx_msg = RxMsg() for i in range(100): tx_msg.rand_burst() rx_msg.rand_burst() tx_msg.rand_hdr() rx_msg.rand_hdr() tx_msg.validate() rx_msg.validate() def _test_enc_dec(self, msg, legacy = False, nope_ind = False): # Prepare a given message (randomize) msg.rand_hdr() # NOPE.ind contains no burst if not nope_ind: msg.rand_burst() else: msg.nope_ind = True msg.mod_type = None msg.tsc_set = None msg.tsc = None # Encode a given message to bytes msg_enc = msg.gen_msg(legacy) # Decode a new message from bytes msg_dec = msg.__class__() msg_dec.parse_msg(msg_enc) # Compare decoded vs the original self._compare_msg(msg, msg_dec) # Validate encoding and decoding def test_enc_dec(self): for ver in Msg.KNOWN_VERSIONS: with self.subTest("TxMsg", ver = ver): msg = TxMsg(ver = ver) self._test_enc_dec(msg) with self.subTest("RxMsg", ver = ver): msg = RxMsg(ver = ver) self._test_enc_dec(msg) if ver >= 1: with self.subTest("RxMsg NOPE.ind", ver = ver): msg = RxMsg(ver = ver) self._test_enc_dec(msg, nope_ind = True) with self.subTest("RxMsg (legacy transceiver)"): msg = RxMsg(ver = 0) self._test_enc_dec(msg, legacy = True) # Validate bit conversations def test_bit_conv(self): usbits_ref = list(range(0, 256)) sbits_ref = list(range(-127, 128)) # Test both usbit2sbit() and sbit2usbit() sbits = Msg.usbit2sbit(usbits_ref) usbits = Msg.sbit2usbit(sbits) self.assertEqual(usbits[:255], usbits_ref[:255]) self.assertEqual(usbits[255], 254) # Test both sbit2ubit() and ubit2sbit() ubits = Msg.sbit2ubit(sbits_ref) self.assertEqual(ubits, ([1] * 127 + [0] * 128)) sbits = Msg.ubit2sbit(ubits) self.assertEqual(sbits, ([-127] * 127 + [127] * 128)) def _test_transform(self, msg): # Prepare given messages msg.rand_hdr() msg.rand_burst() # Perform message transformation if isinstance(msg, TxMsg): msg_trans = msg.trans() else: msg_trans = msg.trans() self.assertEqual(msg_trans.ver, msg.ver) self.assertEqual(msg_trans.fn, msg.fn) self.assertEqual(msg_trans.tn, msg.tn) if isinstance(msg, RxMsg): burst = Msg.sbit2ubit(msg.burst) self.assertEqual(msg_trans.burst, burst) else: burst = Msg.ubit2sbit(msg.burst) self.assertEqual(msg_trans.burst, burst) # Validate message transformation def test_transform(self): for ver in Msg.KNOWN_VERSIONS: with self.subTest("TxMsg", ver = ver): msg = TxMsg(ver = ver) self._test_transform(msg) with self.subTest("RxMsg", ver = ver): msg = RxMsg(ver = ver) self._test_transform(msg) if __name__ == '__main__': unittest.main()