123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- # python-cc1101 - Python Library to Transmit RF Signals via CC1101 Transceivers
- #
- # Copyright (C) 2020 Fabian Peter Hammerle <fabian@hammerle.me>
- #
- # 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 3 of the License, or
- # 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.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <https://www.gnu.org/licenses/>.
- import io
- import logging
- import unittest.mock
- import pytest
- import cc1101._cli
- from cc1101.options import PacketLengthMode, SyncMode
- # pylint: disable=protected-access,too-many-positional-arguments
- @pytest.mark.parametrize(
- (
- "args",
- "base_frequency_hertz",
- "symbol_rate_baud",
- "sync_mode",
- "packet_length_mode",
- "checksum_disabled",
- ),
- (
- ([""], None, None, None, None, False),
- (["", "-f", "433920000"], 433920000, None, None, None, False),
- (
- ["", "--base-frequency-hertz", "868000000"],
- 868000000,
- None,
- None,
- None,
- False,
- ),
- (["", "-r", "10000"], None, 10000, None, None, False),
- (["", "--symbol-rate-baud", "12345"], None, 12345, None, None, False),
- (
- ["", "-s", "no-preamble-and-sync-word"],
- None,
- None,
- SyncMode.NO_PREAMBLE_AND_SYNC_WORD,
- None,
- False,
- ),
- (
- ["", "--sync-mode", "no-preamble-and-sync-word"],
- None,
- None,
- SyncMode.NO_PREAMBLE_AND_SYNC_WORD,
- None,
- False,
- ),
- (
- ["", "--sync-mode", "transmit-16-match-15-bits"],
- None,
- None,
- SyncMode.TRANSMIT_16_MATCH_15_BITS,
- None,
- False,
- ),
- (["", "-l", "fixed"], None, None, None, PacketLengthMode.FIXED, False),
- (
- ["", "--packet-length-mode", "fixed"],
- None,
- None,
- None,
- PacketLengthMode.FIXED,
- False,
- ),
- (
- ["", "--packet-length-mode", "variable"],
- None,
- None,
- None,
- PacketLengthMode.VARIABLE,
- False,
- ),
- (["", "--disable-checksum"], None, None, None, None, True),
- ),
- )
- @pytest.mark.parametrize("payload", (b"", b"message"))
- def test_configure_device(
- args,
- base_frequency_hertz,
- symbol_rate_baud,
- sync_mode,
- packet_length_mode,
- checksum_disabled,
- payload,
- ):
- # pylint: disable=too-many-arguments
- with unittest.mock.patch("cc1101.CC1101") as transceiver_class_mock:
- stdin_mock = unittest.mock.MagicMock()
- stdin_mock.buffer = io.BytesIO(payload)
- with unittest.mock.patch("sys.stdin", stdin_mock):
- with unittest.mock.patch("sys.argv", args):
- cc1101._cli._transmit()
- transceiver_class_mock.assert_called_once_with(lock_spi_device=True)
- with transceiver_class_mock() as transceiver_mock:
- pass
- if base_frequency_hertz is None:
- transceiver_mock.set_base_frequency_hertz.assert_not_called()
- else:
- transceiver_mock.set_base_frequency_hertz.assert_called_once_with(
- base_frequency_hertz
- )
- if symbol_rate_baud is None:
- transceiver_mock.set_symbol_rate_baud.assert_not_called()
- else:
- transceiver_mock.set_symbol_rate_baud.assert_called_once_with(symbol_rate_baud)
- if sync_mode is None:
- transceiver_mock.set_sync_mode.assert_not_called()
- else:
- transceiver_mock.set_sync_mode.assert_called_once_with(sync_mode)
- if packet_length_mode is None: # pylint: disable=duplicate-code
- transceiver_mock.set_packet_length_mode.assert_not_called()
- else:
- transceiver_mock.set_packet_length_mode.assert_called_once_with(
- packet_length_mode
- )
- if packet_length_mode == PacketLengthMode.FIXED:
- transceiver_mock.set_packet_length_bytes.assert_called_with(len(payload))
- else:
- transceiver_mock.set_packet_length_bytes.assert_not_called()
- if checksum_disabled:
- transceiver_mock.disable_checksum.assert_called_once_with()
- else:
- transceiver_mock.disable_checksum.assert_not_called()
- @pytest.mark.parametrize(
- ("args", "output_power_settings"),
- (
- ([""], None),
- (["", "-p", "198"], [198]), # default
- (["", "--output-power", "198"], [198]),
- (["", "-p", "0", "198"], [0, 198]), # OOK
- (
- ["", "-p", "18", "14", "29", "52", "96", "132", "200", "192"],
- [18, 14, 29, 52, 96, 132, 200, 192],
- ),
- ),
- )
- def test_configure_device_output_power(args, output_power_settings):
- with unittest.mock.patch("cc1101.CC1101") as transceiver_class_mock:
- stdin_mock = unittest.mock.MagicMock()
- stdin_mock.buffer = io.BytesIO(b"message")
- with unittest.mock.patch("sys.stdin", stdin_mock):
- with unittest.mock.patch("sys.argv", args):
- cc1101._cli._transmit()
- transceiver_class_mock.assert_called_once_with(lock_spi_device=True)
- with transceiver_class_mock() as transceiver_mock:
- pass
- if output_power_settings:
- transceiver_mock.set_output_power.assert_called_with(output_power_settings)
- else:
- transceiver_mock.set_output_power.assert_not_called()
- @pytest.mark.parametrize(
- ("args", "root_log_level", "log_format"),
- (
- ([""], logging.INFO, "%(message)s"),
- (
- ["", "--debug"],
- logging.DEBUG,
- "%(asctime)s:%(levelname)s:%(name)s:%(funcName)s:%(message)s",
- ),
- ),
- )
- def test_root_log_level(args, root_log_level, log_format):
- stdin_mock = unittest.mock.MagicMock()
- stdin_mock.buffer = io.BytesIO(b"")
- with unittest.mock.patch("cc1101.CC1101"), unittest.mock.patch(
- "sys.stdin", stdin_mock
- ), unittest.mock.patch("sys.argv", args), unittest.mock.patch(
- "logging.basicConfig"
- ) as logging_basic_config_mock:
- cc1101._cli._transmit()
- logging_basic_config_mock.assert_called_once()
- assert logging_basic_config_mock.call_args[1]["level"] == root_log_level
- assert logging_basic_config_mock.call_args[1]["format"] == log_format
- @pytest.mark.parametrize("payload", (b"", b"message"))
- def test_logging(caplog, payload):
- # pylint: disable=too-many-arguments
- stdin_mock = unittest.mock.MagicMock()
- stdin_mock.buffer = io.BytesIO(payload)
- with unittest.mock.patch("sys.stdin", stdin_mock), unittest.mock.patch(
- "sys.argv", [""]
- ), unittest.mock.patch("cc1101.CC1101") as transceiver_class_mock, caplog.at_level(
- logging.DEBUG
- ):
- with transceiver_class_mock() as transceiver_mock:
- transceiver_mock.__str__.return_value = "dummy"
- cc1101._cli._transmit()
- assert len(caplog.records) == 2
- assert caplog.records[0].name == "cc1101._cli"
- assert caplog.records[0].levelno == logging.DEBUG
- assert caplog.records[0].message.startswith(
- "args=Namespace(base_frequency_hertz=None, "
- )
- assert caplog.record_tuples[1] == ("cc1101._cli", logging.INFO, "dummy")
|