#!/usr/bin/env python # coding: utf-8 import unittest import sys from math import isinf, isnan from copy import copy, deepcopy from hypothesis import given, settings, reproduce_failure import hypothesis.strategies as st from can import Message class TestMessageClass(unittest.TestCase): """ This test tries many inputs to the message class constructor and then sanity checks all methods and ensures that nothing crashes. It also checks whether Message._check() allows all valid can frames. """ @given( timestamp=st.floats(min_value=0.0), arbitration_id=st.integers(), is_extended_id=st.booleans(), is_remote_frame=st.booleans(), is_error_frame=st.booleans(), channel=st.one_of(st.text(), st.integers()), dlc=st.integers(min_value=0, max_value=8), data=st.one_of(st.binary(min_size=0, max_size=8), st.none()), is_fd=st.booleans(), bitrate_switch=st.booleans(), error_state_indicator=st.booleans(), ) @settings(max_examples=2000) def test_methods(self, **kwargs): is_valid = not ( ( not kwargs["is_remote_frame"] and (len(kwargs["data"] or []) != kwargs["dlc"]) ) or (kwargs["arbitration_id"] >= 0x800 and not kwargs["is_extended_id"]) or kwargs["arbitration_id"] >= 0x20000000 or kwargs["arbitration_id"] < 0 or (kwargs["is_remote_frame"] and kwargs["is_error_frame"]) or (kwargs["is_remote_frame"] and len(kwargs["data"] or []) > 0) or ( (kwargs["bitrate_switch"] or kwargs["error_state_indicator"]) and not kwargs["is_fd"] ) or isnan(kwargs["timestamp"]) or isinf(kwargs["timestamp"]) ) # this should return normally and not throw an exception message = Message(check=is_valid, **kwargs) if kwargs["data"] is None or kwargs["is_remote_frame"]: kwargs["data"] = bytearray() if not is_valid and not kwargs["is_remote_frame"]: with self.assertRaises(ValueError): Message(check=True, **kwargs) self.assertGreater(len(str(message)), 0) self.assertGreater(len(message.__repr__()), 0) if is_valid: self.assertEqual(len(message), kwargs["dlc"]) self.assertTrue(bool(message)) self.assertGreater(len("{}".format(message)), 0) _ = "{}".format(message) with self.assertRaises(Exception): _ = "{somespec}".format(message) if sys.version_info.major > 2: self.assertEqual(bytearray(bytes(message)), kwargs["data"]) # check copies and equalities if is_valid: self.assertEqual(message, message) normal_copy = copy(message) deep_copy = deepcopy(message) for other in (normal_copy, deep_copy, message): self.assertTrue(message.equals(other, timestamp_delta=None)) self.assertTrue(message.equals(other)) self.assertTrue(message.equals(other, timestamp_delta=0)) if __name__ == "__main__": unittest.main()