예제 #1
0
파일: str_test.py 프로젝트: onkelbeh/xknx
    def test_remote_value(self):
        """Test string representation of remote value."""
        xknx = XKNX()
        remote_value = RemoteValue(
            xknx,
            group_address="1/2/3",
            device_name="MyDevice",
            group_address_state="1/2/4",
        )
        assert (
            str(remote_value) ==
            '<RemoteValue device_name="MyDevice" feature_name="Unknown" <1/2/3, 1/2/4, [], None /> />'
        )

        remote_value.value = 34
        assert (str(remote_value) ==
                '<RemoteValue device_name="MyDevice" feature_name="Unknown" '
                "<1/2/3, 1/2/4, [], 34 /> />")

        remote_value_passive = RemoteValue(
            xknx,
            group_address=["1/2/3", "1/2/4", "i-test"],
            device_name="MyDevice",
        )
        assert (
            str(remote_value_passive) ==
            "<RemoteValue device_name=\"MyDevice\" feature_name=\"Unknown\" <1/2/3, None, ['1/2/4', 'i-test'], None /> />"
        )
예제 #2
0
 def test_register_unregister(self):
     """Test register and unregister."""
     xknx = XKNX(loop=self.loop)
     self.assertEqual(len(xknx.state_updater._workers), 0)
     # register when state address and sync_state is set
     remote_value_1 = RemoteValue(xknx,
                                  sync_state=True,
                                  group_address_state=GroupAddress("1/1/1"))
     self.assertEqual(len(xknx.state_updater._workers), 1)
     # don't register when sync_state is False
     remote_value_2 = RemoteValue(xknx,
                                  sync_state=False,
                                  group_address_state=GroupAddress("1/1/1"))
     self.assertEqual(len(xknx.state_updater._workers), 1)
     # manual registration
     xknx.state_updater.register_remote_value(remote_value_2)
     self.assertEqual(len(xknx.state_updater._workers), 2)
     # manual unregister
     xknx.state_updater.unregister_remote_value(remote_value_1)
     # only remote_value_2 remaining
     self.assertEqual(len(xknx.state_updater._workers), 1)
     self.assertEqual(
         list(xknx.state_updater._workers.keys())[0], id(remote_value_2))
     # unregister on RemoteValue.__del__()
     remote_value_2.__del__()
     self.assertEqual(len(xknx.state_updater._workers), 0)
예제 #3
0
 def test_register_unregister(self):
     """Test register and unregister."""
     xknx = XKNX()
     assert len(xknx.state_updater._workers) == 0
     # register when state address and sync_state is set
     remote_value_1 = RemoteValue(xknx,
                                  sync_state=True,
                                  group_address_state=GroupAddress("1/1/1"))
     assert len(xknx.state_updater._workers) == 1
     # don't register when sync_state is False
     remote_value_2 = RemoteValue(xknx,
                                  sync_state=False,
                                  group_address_state=GroupAddress("1/1/1"))
     assert len(xknx.state_updater._workers) == 1
     # manual registration
     xknx.state_updater.register_remote_value(remote_value_2)
     assert len(xknx.state_updater._workers) == 2
     # manual unregister
     xknx.state_updater.unregister_remote_value(remote_value_1)
     # only remote_value_2 remaining
     assert len(xknx.state_updater._workers) == 1
     assert list(
         xknx.state_updater._workers.keys())[0] == id(remote_value_2)
     # unregister on RemoteValue.__del__()
     remote_value_2.__del__()
     assert len(xknx.state_updater._workers) == 0
예제 #4
0
 def test_warn_to_knx(self):
     """Test for warning if to_knx is not implemented."""
     xknx = XKNX(loop=self.loop)
     remote_value = RemoteValue(xknx)
     with patch('logging.Logger.warning') as mock_warn:
         remote_value.to_knx(23)
         mock_warn.assert_called_with('to_knx not implemented for %s',
                                      'RemoteValue')
예제 #5
0
 def test_warn_payload_valid(self):
     """Test for warning if payload_valid is not implemented."""
     xknx = XKNX(loop=self.loop)
     remote_value = RemoteValue(xknx)
     with patch('logging.Logger.warning') as mock_warn:
         remote_value.payload_valid(DPTBinary(0))
         mock_warn.assert_called_with(
             'payload_valid not implemented for %s', 'RemoteValue')
예제 #6
0
 def test_warn_to_knx(self):
     """Test for warning if to_knx is not implemented."""
     xknx = XKNX()
     remote_value = RemoteValue(xknx)
     with patch("logging.Logger.warning") as mock_warn:
         remote_value.to_knx(23)
         mock_warn.assert_called_with("'to_knx()' not implemented for %s",
                                      "RemoteValue")
예제 #7
0
 def test_warn_from_knx(self):
     """Test for warning if from_knx is not implemented."""
     xknx = XKNX(loop=self.loop)
     remote_value = RemoteValue(xknx)
     with patch("logging.Logger.warning") as mock_warn:
         remote_value.from_knx(DPTBinary(0))
         mock_warn.assert_called_with("'from_knx()' not implemented for %s",
                                      "RemoteValue")
예제 #8
0
 def test_warn_payload_valid(self):
     """Test for warning if payload_valid is not implemented."""
     xknx = XKNX()
     remote_value = RemoteValue(xknx)
     with patch("logging.Logger.warning") as mock_warn:
         remote_value.payload_valid(DPTBinary(0))
         mock_warn.assert_called_with(
             "'payload_valid()' not implemented for %s", "RemoteValue")
예제 #9
0
 def test_info_set_uninitialized(self):
     """Test for info if RemoteValue is not initialized."""
     xknx = XKNX(loop=self.loop)
     remote_value = RemoteValue(xknx)
     with patch('logging.Logger.info') as mock_info:
         self.loop.run_until_complete(asyncio.Task(remote_value.set(23)))
         mock_info.assert_called_with(
             'Setting value of uninitialized device: %s (value: %s)',
             'Unknown', 23)
예제 #10
0
 def test_info_set_unwritable(self):
     """Test for warning if RemoteValue is read only."""
     xknx = XKNX(loop=self.loop)
     remote_value = RemoteValue(xknx,
                                group_address_state=GroupAddress('1/2/3'))
     with patch('logging.Logger.warning') as mock_info:
         self.loop.run_until_complete(asyncio.Task(remote_value.set(23)))
         mock_info.assert_called_with(
             'Attempted to set value for non-writable device: %s (value: %s)',
             'Unknown', 23)
예제 #11
0
 def test_info_set_uninitialized(self):
     """Test for info if RemoteValue is not initialized."""
     xknx = XKNX()
     remote_value = RemoteValue(xknx)
     with patch("logging.Logger.info") as mock_info:
         self.loop.run_until_complete(remote_value.set(23))
         mock_info.assert_called_with(
             "Setting value of uninitialized device: %s - %s (value: %s)",
             "Unknown",
             "Unknown",
             23,
         )
예제 #12
0
 def test_info_set_unwritable(self):
     """Test for warning if RemoteValue is read only."""
     xknx = XKNX()
     remote_value = RemoteValue(xknx, group_address_state=GroupAddress("1/2/3"))
     with patch("logging.Logger.warning") as mock_info:
         self.loop.run_until_complete(remote_value.set(23))
         mock_info.assert_called_with(
             "Attempted to set value for non-writable device: %s - %s (value: %s)",
             "Unknown",
             "Unknown",
             23,
         )
예제 #13
0
    def test_process_invalid_payload(self):
        """Test if exception is raised when processing telegram with invalid payload."""
        xknx = XKNX()
        remote_value = RemoteValue(xknx)
        with patch("xknx.remote_value.RemoteValue.payload_valid") as patch_valid, patch(
            "xknx.remote_value.RemoteValue.has_group_address"
        ) as patch_has_group_address:
            patch_valid.return_value = False
            patch_has_group_address.return_value = True

            telegram = Telegram(GroupAddress("1/2/1"), payload=DPTArray((0x01, 0x02)))
            with self.assertRaises(CouldNotParseTelegram):
                self.loop.run_until_complete(remote_value.process(telegram))
예제 #14
0
 def test_remote_value(self):
     """Test string representation of remote value."""
     xknx = XKNX(loop=self.loop)
     remote_value = RemoteValue(
         xknx,
         group_address='1/2/3',
         device_name="MyDevice",
         group_address_state='1/2/4')
     self.assertEqual(
         str(remote_value),
         '<RemoteValue device_name="MyDevice" GroupAddress("1/2/3")/GroupAddress("1/2/4")/None/None/>')
     remote_value.payload = DPTArray([0x01, 0x02])
     self.assertEqual(
         str(remote_value),
         '<RemoteValue device_name="MyDevice" GroupAddress("1/2/3")/GroupAddress("1/2/4")/<DPTArray value="[0x1,0x2]" />/None/>')
예제 #15
0
    async def test_process_unsupported_payload(self):
        """Test warning is logged when processing telegram with unsupported payload."""
        xknx = XKNX()
        remote_value = RemoteValue(xknx)
        telegram = Telegram(
            destination_address=GroupAddress("1/2/1"),
            payload=GroupValueWrite(DPTArray((0x01, 0x02))),
        )
        with patch(
                "xknx.remote_value.RemoteValue.payload_valid"
        ) as patch_valid, patch(
                "xknx.remote_value.RemoteValue.has_group_address"
        ) as patch_has_group_address, patch(
                "xknx.remote_value.RemoteValue.from_knx") as patch_from, patch(
                    "logging.Logger.warning") as mock_warning:
            patch_valid.return_value = telegram.payload.value
            patch_has_group_address.return_value = True
            patch_from.side_effect = ConversionError("TestError")

            assert await remote_value.process(telegram) is False
            mock_warning.assert_called_once_with(
                "Can not process %s for %s - %s: %s",
                telegram,
                "Unknown",
                "Unknown",
                ConversionError("TestError"),
            )
예제 #16
0
    async def test_set_value(self):
        """Test set_value awaitable."""
        xknx = XKNX()
        remote_value = RemoteValue(xknx)
        remote_value.to_knx = lambda value: DPTArray(
            DPT2ByteFloat.to_knx(value))
        remote_value.after_update_cb = AsyncMock()

        await remote_value.update_value(3.3)
        assert remote_value.value == 3.3
        remote_value.after_update_cb.assert_called_once()
        assert xknx.telegrams.qsize() == 0
        # invalid value raises ConversionError
        with pytest.raises(ConversionError):
            await remote_value.update_value("a")
        assert remote_value.value == 3.3
예제 #17
0
 def test_remote_value(self):
     """Test string representation of remote value."""
     xknx = XKNX()
     remote_value = RemoteValue(
         xknx,
         group_address="1/2/3",
         device_name="MyDevice",
         group_address_state="1/2/4",
     )
     self.assertEqual(
         str(remote_value),
         '<RemoteValue device_name="MyDevice" feature_name="Unknown" GroupAddress("1/2/3")/GroupAddress("1/2/4")/None/None/>',
     )
     remote_value.payload = DPTArray([0x01, 0x02])
     self.assertEqual(
         str(remote_value),
         '<RemoteValue device_name="MyDevice" feature_name="Unknown" '
         'GroupAddress("1/2/3")/GroupAddress("1/2/4")/<DPTArray value="[0x1,0x2]" />/None/>',
     )
예제 #18
0
    def test_process_unsupported_payload(self):
        """Test if exception is raised when processing telegram with unsupported payload."""
        xknx = XKNX()
        remote_value = RemoteValue(xknx)
        with patch("xknx.remote_value.RemoteValue.payload_valid") as patch_valid, patch(
            "xknx.remote_value.RemoteValue.has_group_address"
        ) as patch_has_group_address:
            patch_valid.return_value = False
            patch_has_group_address.return_value = True

            telegram = Telegram(
                destination_address=GroupAddress("1/2/1"),
                payload=object(),
            )
            with self.assertRaisesRegex(
                CouldNotParseTelegram,
                r".*payload not a GroupValueWrite or GroupValueResponse.*",
            ):
                self.loop.run_until_complete(remote_value.process(telegram))
예제 #19
0
 def test_process_listening_address(self):
     """Test if listening group addresses are processed."""
     xknx = XKNX()
     remote_value = RemoteValue(
         xknx, group_address="1/2/3", passive_group_addresses=["1/1/1"]
     )
     self.assertTrue(remote_value.writable)
     self.assertFalse(remote_value.readable)
     # RemoteValue is initialized with only passive group address
     self.assertTrue(remote_value.initialized)
     with patch("xknx.remote_value.RemoteValue.payload_valid") as patch_valid:
         patch_valid.return_value = True
         test_payload = DPTArray((0x01, 0x02))
         telegram = Telegram(GroupAddress("1/1/1"), payload=test_payload)
         self.assertTrue(
             self.loop.run_until_complete(
                 asyncio.Task(remote_value.process(telegram))
             )
         )
         self.assertEqual(remote_value.payload, test_payload)
예제 #20
0
 async def test_stat_updater_default(self, default, sync_state_value,
                                     expected_interval,
                                     expected_tracker_type):
     """Test setting a default for StateUpdater."""
     xknx = XKNX(state_updater=default)
     remote_value = RemoteValue(xknx,
                                sync_state=sync_state_value,
                                group_address_state=GroupAddress("1/1/1"))
     assert (xknx.state_updater._workers[id(remote_value)].update_interval
             == expected_interval * 60)
     assert (xknx.state_updater._workers[id(remote_value)].tracker_type ==
             expected_tracker_type)
예제 #21
0
    async def test_process_invalid_payload(self):
        """Test if exception is raised when processing telegram with invalid payload."""
        xknx = XKNX()
        remote_value = RemoteValue(xknx)
        with patch("xknx.remote_value.RemoteValue.has_group_address",
                   remote_value=True):

            telegram = Telegram(
                destination_address=GroupAddress("1/2/1"),
                payload=GroupValueWrite(DPTArray((0x01, 0x02))),
            )
            assert await remote_value.process(telegram) is False
예제 #22
0
    def test_state_updater_start_update_stop(self):
        """Test start, update_received and stop of StateUpdater."""
        xknx = XKNX()
        remote_value_1 = RemoteValue(xknx,
                                     sync_state=True,
                                     group_address_state=GroupAddress("1/1/1"))
        remote_value_2 = RemoteValue(xknx,
                                     sync_state=True,
                                     group_address_state=GroupAddress("1/1/2"))
        xknx.state_updater._workers[id(remote_value_1)] = Mock()
        xknx.state_updater._workers[id(remote_value_2)] = Mock()

        assert not xknx.state_updater.started
        xknx.connection_manager._state = XknxConnectionState.CONNECTED
        xknx.state_updater.start()
        assert xknx.state_updater.started
        # start
        xknx.state_updater._workers[id(
            remote_value_1)].start.assert_called_once_with()
        xknx.state_updater._workers[id(
            remote_value_2)].start.assert_called_once_with()
        # update
        xknx.state_updater.update_received(remote_value_2)
        xknx.state_updater._workers[id(
            remote_value_1)].update_received.assert_not_called()
        xknx.state_updater._workers[id(
            remote_value_2)].update_received.assert_called_once_with()
        # stop
        xknx.state_updater.stop()
        assert not xknx.state_updater.started
        xknx.state_updater._workers[id(
            remote_value_1)].stop.assert_called_once_with()
        xknx.state_updater._workers[id(
            remote_value_2)].stop.assert_called_once_with()
        # don't update when not started
        xknx.state_updater.update_received(remote_value_1)
        xknx.state_updater._workers[id(
            remote_value_1)].update_received.assert_not_called()
예제 #23
0
    def test_state_updater_start_update_stop(self):
        """Test start, update_received and stop of StateUpdater."""
        xknx = XKNX(loop=self.loop)
        remote_value_1 = RemoteValue(xknx,
                                     sync_state=True,
                                     group_address_state=GroupAddress("1/1/1"))
        remote_value_2 = RemoteValue(xknx,
                                     sync_state=True,
                                     group_address_state=GroupAddress("1/1/2"))
        xknx.state_updater._workers[id(remote_value_1)] = Mock()
        xknx.state_updater._workers[id(remote_value_2)] = Mock()

        self.assertFalse(xknx.state_updater.started)
        xknx.state_updater.start()
        self.assertTrue(xknx.state_updater.started)
        # start
        xknx.state_updater._workers[id(
            remote_value_1)].start.assert_called_once_with()
        xknx.state_updater._workers[id(
            remote_value_2)].start.assert_called_once_with()
        # update
        xknx.state_updater.update_received(remote_value_2)
        xknx.state_updater._workers[id(
            remote_value_1)].update_received.assert_not_called()
        xknx.state_updater._workers[id(
            remote_value_2)].update_received.assert_called_once_with()
        # stop
        xknx.state_updater.stop()
        self.assertFalse(xknx.state_updater.started)
        xknx.state_updater._workers[id(
            remote_value_1)].stop.assert_called_once_with()
        xknx.state_updater._workers[id(
            remote_value_2)].stop.assert_called_once_with()
        # don't update when not started
        xknx.state_updater.update_received(remote_value_1)
        xknx.state_updater._workers[id(
            remote_value_1)].update_received.assert_not_called()
예제 #24
0
 async def test_process_passive_address(self):
     """Test if passive group addresses are processed."""
     xknx = XKNX()
     remote_value = RemoteValue(xknx, group_address=["1/2/3", "1/1/1"])
     assert remote_value.writable
     assert not remote_value.readable
     # RemoteValue is initialized with only passive group address
     assert remote_value.initialized
     with patch("xknx.remote_value.RemoteValue.payload_valid"
                ) as patch_always_valid:
         patch_always_valid.side_effect = lambda payload: payload
         test_payload = DPTArray((0x01, 0x02))
         telegram = Telegram(
             destination_address=GroupAddress("1/1/1"),
             payload=GroupValueWrite(test_payload),
         )
         assert await remote_value.process(telegram)
         assert remote_value.telegram.payload.value == test_payload
예제 #25
0
    async def test_process_invalid_payload(self):
        """Test if exception is raised when processing telegram with invalid payload."""
        xknx = XKNX()
        remote_value = RemoteValue(xknx)
        with patch("xknx.remote_value.RemoteValue.payload_valid"
                   ) as patch_valid, patch(
                       "xknx.remote_value.RemoteValue.has_group_address"
                   ) as patch_has_group_address:
            patch_valid.return_value = None
            patch_has_group_address.return_value = True

            telegram = Telegram(
                destination_address=GroupAddress("1/2/1"),
                payload=GroupValueWrite(DPTArray((0x01, 0x02))),
            )
            with pytest.raises(CouldNotParseTelegram,
                               match=r".*payload invalid.*"):
                await remote_value.process(telegram)
예제 #26
0
    async def test_process_unsupported_payload(self):
        """Test if exception is raised when processing telegram with unsupported payload."""
        xknx = XKNX()
        remote_value = RemoteValue(xknx)
        with patch("xknx.remote_value.RemoteValue.payload_valid"
                   ) as patch_valid, patch(
                       "xknx.remote_value.RemoteValue.has_group_address"
                   ) as patch_has_group_address:
            patch_valid.return_value = False
            patch_has_group_address.return_value = True

            telegram = Telegram(destination_address=GroupAddress("1/2/1"),
                                payload=object())
            with pytest.raises(
                    CouldNotParseTelegram,
                    match=
                    r".*payload not a GroupValueWrite or GroupValueResponse.*",
            ):
                await remote_value.process(telegram)
예제 #27
0
    async def test_get_set_value(self):
        """Test value getter and setter."""
        xknx = XKNX()
        remote_value = RemoteValue(xknx)
        remote_value.to_knx = lambda value: DPTArray(
            DPT2ByteFloat.to_knx(value))
        remote_value.after_update_cb = AsyncMock()

        assert remote_value.value is None
        remote_value.value = 2.2
        assert remote_value.value == 2.2
        # invalid value raises ConversionError
        with pytest.raises(ConversionError):
            remote_value.value = "a"
        # new value is used in response Telegram
        test_payload = remote_value.to_knx(2.2)
        remote_value._send = AsyncMock()
        await remote_value.respond()
        remote_value._send.assert_called_with(test_payload, response=True)
        # callback is not called when setting value programmatically
        remote_value.after_update_cb.assert_not_called()
        # no Telegram was sent to the queue
        assert xknx.telegrams.qsize() == 0
예제 #28
0
    def test_tracker_parser_invalid_options(self, logging_warning_mock):
        """Test parsing invalid tracker options."""
        xknx = XKNX()

        def _get_only_tracker() -> _StateTracker:
            # _workers is unordered so it just works with 1 item
            self.assertEqual(len(xknx.state_updater._workers), 1)
            _tracker = next(iter(xknx.state_updater._workers.values()))
            return _tracker

        # INVALID string
        remote_value_invalid = RemoteValue(
            xknx,
            sync_state="invalid",
            group_address_state=GroupAddress("1/1/1"))
        logging_warning_mock.assert_called_once_with(
            'Could not parse StateUpdater tracker_options "%s" for %s. Using default %s %s minutes.',
            "invalid",
            remote_value_invalid,
            StateTrackerType.EXPIRE,
            60,
        )
        self.assertEqual(_get_only_tracker().tracker_type,
                         StateTrackerType.EXPIRE)
        self.assertEqual(_get_only_tracker().update_interval, 60 * 60)
        remote_value_invalid.__del__()
        logging_warning_mock.reset_mock()
        # intervall too long
        remote_value_long = RemoteValue(
            xknx, sync_state=1441, group_address_state=GroupAddress("1/1/1"))
        logging_warning_mock.assert_called_once_with(
            "StateUpdater interval of %s to long for %s. Using maximum of %s minutes (1 day)",
            1441,
            remote_value_long,
            1440,
        )
        remote_value_long.__del__()
예제 #29
0
    def test_eq(self):
        """Test __eq__ operator."""
        xknx = XKNX()
        remote_value1 = RemoteValue(xknx, group_address=GroupAddress("1/1/1"))
        remote_value2 = RemoteValue(xknx, group_address=GroupAddress("1/1/1"))
        remote_value3 = RemoteValue(xknx, group_address=GroupAddress("1/1/2"))
        remote_value4 = RemoteValue(xknx, group_address=GroupAddress("1/1/1"))
        remote_value4.fnord = "fnord"

        def _callback():
            pass

        remote_value5 = RemoteValue(xknx,
                                    group_address=GroupAddress("1/1/1"),
                                    after_update_cb=_callback())

        self.assertEqual(remote_value1, remote_value2)
        self.assertEqual(remote_value2, remote_value1)
        self.assertNotEqual(remote_value1, remote_value3)
        self.assertNotEqual(remote_value3, remote_value1)
        self.assertNotEqual(remote_value1, remote_value4)
        self.assertNotEqual(remote_value4, remote_value1)
        self.assertEqual(remote_value1, remote_value5)
        self.assertEqual(remote_value5, remote_value1)
예제 #30
0
    def test_eq(self):
        """Test __eq__ operator."""
        xknx = XKNX()
        remote_value1 = RemoteValue(xknx, group_address=GroupAddress("1/1/1"))
        remote_value2 = RemoteValue(xknx, group_address=GroupAddress("1/1/1"))
        remote_value3 = RemoteValue(xknx, group_address=GroupAddress("1/1/2"))
        remote_value4 = RemoteValue(xknx, group_address=GroupAddress("1/1/1"))
        remote_value4.fnord = "fnord"

        def _callback():
            pass

        remote_value5 = RemoteValue(xknx,
                                    group_address=GroupAddress("1/1/1"),
                                    after_update_cb=_callback())

        assert remote_value1 == remote_value2
        assert remote_value2 == remote_value1
        assert remote_value1 != remote_value3
        assert remote_value3 != remote_value1
        assert remote_value1 != remote_value4
        assert remote_value4 != remote_value1
        assert remote_value1 == remote_value5
        assert remote_value5 == remote_value1