返回教程正文

配套源码

test_frame.py

app/tests/test_frame.py
generic_can Brick:在 VENTUNO Q 上自定义 CAN 报文app/tests/test_frame.py
Python129 行
"""CanFrame边界和数据规范化测试。"""

import unittest

from generic_can import CANConfigurationError, CanFrame


class CanFrameTests(unittest.TestCase):
    """验证标准帧、扩展帧、Classical CAN和CAN FD边界。"""

    def test_classical_and_extended_boundaries(self):
        """
        @description         : 验证标准ID和扩展ID的最大合法值
        @param self          : 当前测试用例
        @return              : 无
        """
        self.assertEqual(CanFrame(0x7FF).arbitration_id, 0x7FF)
        self.assertEqual(
            CanFrame(0x1FFFFFFF, is_extended=True).arbitration_id,
            0x1FFFFFFF,
        )

    def test_rejects_invalid_identifiers(self):
        """
        @description         : 验证越界ID和布尔ID会被拒绝
        @param self          : 当前测试用例
        @return              : 无
        """
        for arguments in (
            {"arbitration_id": -1},
            {"arbitration_id": 0x800},
            {"arbitration_id": 0x20000000, "is_extended": True},
            {"arbitration_id": True},
        ):
            with self.subTest(arguments=arguments):
                with self.assertRaises(CANConfigurationError):
                    CanFrame(**arguments)

    def test_classical_can_accepts_at_most_eight_bytes(self):
        """
        @description         : 验证Classical CAN DATA长度上限为8字节
        @param self          : 当前测试用例
        @return              : 无
        """
        self.assertEqual(len(CanFrame(1, range(8)).data), 8)
        with self.assertRaises(CANConfigurationError):
            CanFrame(1, range(9))

    def test_can_fd_accepts_at_most_sixty_four_bytes(self):
        """
        @description         : 验证CAN FD DATA长度上限和BRS约束
        @param self          : 当前测试用例
        @return              : 无
        """
        frame = CanFrame(1, range(64), is_fd=True, bitrate_switch=True)
        self.assertEqual(len(frame.data), 64)
        with self.assertRaises(CANConfigurationError):
            CanFrame(1, bytes(65), is_fd=True)
        with self.assertRaises(CANConfigurationError):
            CanFrame(1, bitrate_switch=True)

    def test_can_fd_accepts_only_valid_dlc_payload_lengths(self):
        """
        @description         : 验证CAN FD只接受能够直接对应DLC的DATA长度
        @param self          : 当前测试用例
        @return              : 无
        """
        valid_lengths = (
            0,
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            12,
            16,
            20,
            24,
            32,
            48,
            64,
        )
        for length in valid_lengths:
            with self.subTest(length=length):
                self.assertEqual(
                    len(CanFrame(1, bytes(length), is_fd=True).data),
                    length,
                )

    def test_can_fd_rejects_non_dlc_payload_lengths(self):
        """
        @description         : 验证CAN FD拒绝不能直接对应DLC的DATA长度
        @param self          : 当前测试用例
        @return              : 无
        """
        invalid_lengths = (9, 10, 11, 13, 15, 17, 31, 33, 47, 49, 63, 65)
        for length in invalid_lengths:
            with self.subTest(length=length):
                with self.assertRaises(CANConfigurationError):
                    CanFrame(1, bytes(length), is_fd=True)

    def test_normalizes_mutable_payload(self):
        """
        @description         : 验证可变字节序列会被复制成不可变bytes
        @param self          : 当前测试用例
        @return              : 无
        """
        source = bytearray([1, 2])
        frame = CanFrame(1, source)
        source[0] = 9
        self.assertEqual(frame.data, b"\x01\x02")

    def test_rejects_text_and_integer_payloads(self):
        """
        @description         : 验证字符串和整数不会被意外转换成CAN DATA
        @param self          : 当前测试用例
        @return              : 无
        """
        for value in ("01 02", 2, True):
            with self.subTest(value=value):
                with self.assertRaises(CANConfigurationError):
                    CanFrame(1, value)


if __name__ == "__main__":
    unittest.main()