コード例 #1
0
ファイル: test_file.py プロジェクト: Rogdham/python-xz
def test_read_default_strategy(max_block_read_nb: Optional[int]) -> None:
    fileobj = Mock(wraps=BytesIO(FILE_BYTES_MANY_SMALL_BLOCKS))

    max_block_read_nb_ = 8 if max_block_read_nb is None else max_block_read_nb

    with XZFile(
            fileobj,
            block_read_strategy=None if max_block_read_nb is None else
            RollingBlockReadStrategy(max_block_read_nb),
    ) as xz_file:
        fileobj.method_calls.clear()

        order = list(range(10))

        # read one byte of each block
        for i in order:
            xz_file.seek(i * 10 + 2)
            assert xz_file.read(1) == b"2"
            assert fileobj.method_calls == [
                # read whole block at once
                call.seek(12 + 36 * i, SEEK_SET),
                call.read(36),
            ], i
            fileobj.method_calls.clear()

        # read next byte of each block in reverse order
        order.reverse()
        for i in order:
            xz_file.seek(i * 10 + 3)
            assert xz_file.read(1) == b"3"
            if i < 10 - (max_block_read_nb_):
                # decompressor has been cleared, read again
                assert fileobj.method_calls == [
                    # read whole block at once
                    call.seek(12 + 36 * i, SEEK_SET),
                    call.read(36),
                ], i
                fileobj.method_calls.clear()
            else:
                # data cached in decompressor, no need to read
                assert not fileobj.method_calls

        if max_block_read_nb_ > 1:
            # test that alternating between two blocks is fast
            for i in (0, 9):
                xz_file.seek(i * 10 + 4)
                assert xz_file.read(1) == b"4"
            fileobj.method_calls.clear()
            for i in (0, 9):
                xz_file.seek(i * 10 + 5)
                assert xz_file.read(1) == b"5"
                # data cached in decompressor, no need to read
                assert not fileobj.method_calls
コード例 #2
0
def test_parse(
        data_pattern_locate: Callable[[bytes], Tuple[int, int]]) -> None:
    fileobj = Mock(wraps=BytesIO(b"\xff" * 1000 + STREAM_BYTES +
                                 b"\xee" * 1000))
    fileobj.seek(-1000, SEEK_END)
    fileobj.method_calls.clear()

    # parse stream
    stream = XZStream.parse(fileobj)
    assert stream.check == 1
    assert len(stream) == 190
    assert stream.block_boundaries == [0, 100]

    # make sure we don't read the blocks
    assert fileobj.method_calls == [
        call.seek(-12, SEEK_CUR),
        call.read(12),
        call.seek(-24, SEEK_CUR),
        call.read(12),
        call.seek(-204, SEEK_CUR),  # blocks are skipped over here
        call.read(12),
        call.seek(-12, SEEK_CUR),
    ]

    # fileobj should be at the begining of the stream
    assert fileobj.tell() == 1000

    # read from start
    assert data_pattern_locate(stream.read(20)) == (0, 20)

    # read from middle of a block
    stream.seek(40)
    assert data_pattern_locate(stream.read(20)) == (40, 20)

    # read accross two blocks
    stream.seek(90)
    assert data_pattern_locate(stream.read(20)) == (90, 20)

    # read middle of an other block
    stream.seek(160)
    assert data_pattern_locate(stream.read(20)) == (160, 20)

    # go backward and read
    stream.seek(130)
    assert data_pattern_locate(stream.read(20)) == (130, 20)

    # read in previous block (going backward from last read in that block)
    stream.seek(60)
    assert data_pattern_locate(stream.read(20)) == (60, 20)

    # read until end
    stream.seek(170)
    assert data_pattern_locate(stream.read()) == (170, 20)
コード例 #3
0
    def test_read_chunk_data(self, patch_bytesio, patch_zlib):
        chunk0 = XMFChunk(id1=0, id2=32, bytes=28, part=0, offset=100, packed=1234, qty=10)
        chunk0.get_chunk_data_class = MagicMock()
        chunk0.get_chunk_data_class.return_value.flags = ChunkDataV28.flags
        chunk0.get_chunk_data_class.return_value.struct_len = 11
        chunk0.get_chunk_data_class.return_value.from_stream.side_effect = range(1, 11)

        chunk1 = XMFChunk(id1=30, id2=31, bytes=12, part=0, offset=200, packed=5678, qty=5)
        chunk1.get_chunk_data_class = MagicMock()
        chunk1.get_chunk_data_class.return_value.flags = ChunkDataF31.flags
        chunk1.get_chunk_data_class.return_value.struct_len = 12
        chunk1.get_chunk_data_class.return_value.from_stream.side_effect = range(11, 16)
        stream = MagicMock()
        stream.tell.return_value = 101
        self.reader.read_chunk_data(stream=stream, chunks=[chunk0, chunk1])

        chunk0.get_chunk_data_class.assert_called_once_with()
        chunk0.get_chunk_data_class.return_value.from_stream.assert_has_calls([
            call(stream=patch_bytesio.return_value, read_len=28)
            for i in range(10)
        ])

        chunk1.get_chunk_data_class.assert_called_once_with()
        chunk1.get_chunk_data_class.return_value.from_stream.assert_has_calls([
            call(stream=patch_bytesio.return_value, read_len=12)
            for i in range(5)
        ])

        patch_bytesio.assert_has_calls([
            call(patch_zlib.decompress.return_value),
            call(patch_zlib.decompress.return_value),
        ])
        patch_zlib.decompress.assert_has_calls([
            call(stream.read.return_value),
            call(stream.read.return_value),
        ])
        stream.assert_has_calls([
            call.tell(),
            call.seek(101+100),
            call.read(chunk0.packed),
            call.seek(101 + 200),
            call.read(chunk1.packed),
        ])

        self.assertEqual(self.reader.vertices, list(range(1, 11)))
        self.assertEqual(self.reader.faces, list(range(11,16)))
        self.assertEqual(self.reader.flags, ChunkDataV28.flags | ChunkDataF31.flags)
コード例 #4
0
 def test_success(self):
     content = "foo: bar\nbaz: 123\n"
     expected = {'foo': 'bar', 'baz': 123}
     m_body = Mock()
     m_body.read.return_value = content
     m_obj = Mock(key='foo/bar/baz.yml')
     m_obj.get.return_value = {'Body': m_body}
     m_bkt = Mock()
     m_bkt.Object.return_value = m_obj
     with patch('%s.yaml.load' % pbm) as m_load:
         m_load.return_value = expected
         res = self.cls._get_yaml_from_s3(m_bkt, 'foo/bar/baz.yml')
     assert res == expected
     assert m_bkt.mock_calls == [
         call.Object('foo/bar/baz.yml'),
         call.Object().get()
     ]
     assert m_obj.mock_calls == [call.get()]
     assert m_body.mock_calls == [call.read()]
     assert m_load.mock_calls == [call(content, Loader=yaml.FullLoader)]
コード例 #5
0
 def test_cant_load_yaml(self):
     content = "foo: bar\nbaz: 123\n"
     m_body = Mock()
     m_body.read.return_value = content
     m_obj = Mock(key='foo/bar/baz.yml')
     m_obj.get.return_value = {'Body': m_body}
     m_bkt = Mock(name='bname')
     m_bkt.Object.return_value = m_obj
     with patch('%s.yaml.load' % pbm) as m_load:
         m_load.side_effect = NotImplementedError('foo')
         with pytest.raises(RuntimeError) as exc:
             self.cls._get_yaml_from_s3(m_bkt, 'foo/bar/baz.yml')
             assert str(exc.value) == 'ERROR: Unable to load YAML from ' \
                                      'key foo/bar/baz.yml from bucket bname'
     assert m_bkt.mock_calls == [
         call.Object('foo/bar/baz.yml'),
         call.Object().get()
     ]
     assert m_obj.mock_calls == [call.get()]
     assert m_body.mock_calls == [call.read()]
     assert m_load.mock_calls == [call(content, Loader=yaml.FullLoader)]
コード例 #6
0
ファイル: test_s300.py プロジェクト: clda55hnky/HonDash
class TestS300:

    temp_sensor_argvalues = ((51, 69, 156), (40, 80, 175), (31, 91, 195))

    def setup_method(self):
        # we are not unit testing USB features so it may raise a
        # `usb.core.NoBackendError` e.g. on Docker
        with mock.patch(
                "backend.devices.s300.s300.S300.__init__") as m___init__:
            m___init__.return_value = None
            self.s300 = S300()
        self.s300.data4 = [None for _ in range(18)]
        self.s300.data5 = [None for _ in range(21)]
        self.s300.data6 = [None for _ in range(200)]

    def test_init(self):
        with mock.patch("usb.core.find"), mock.patch(
                "threading.Thread.start") as m_start:
            self.s300 = S300()

        assert self.s300.status is True
        # update method in a thread has been tried to start
        assert m_start.called is True

    @pytest.mark.parametrize(
        "s300_version, s300_vendor_id, s300_product_id",
        ((constants.S3003_ID, constants.S3003_ID_VENDOR,
          constants.S3003_ID_PRODUCT), ),
    )
    def test_init_with_all_s300_versions(self, s300_version, s300_vendor_id,
                                         s300_product_id):
        def found_device(idVendor, idProduct):
            if idVendor == s300_vendor_id and idProduct == s300_product_id:
                return MagicMock()
            else:
                return None

        with mock.patch("usb.core.find") as m_find, mock.patch(
                "threading.Thread.start") as m_start:
            m_find.side_effect = found_device
            self.s300 = S300()

        assert self.s300.status is True
        # update method in a thread has been tried to start
        assert m_start.called is True
        assert self.s300.version == s300_version

    def test_init_no_s300_connected(self):
        with mock.patch("usb.core.find") as m_find, mock.patch(
                "threading.Thread.start") as m_start:
            m_find.return_value = None
            self.s300 = S300()

        assert self.s300.status is False
        assert self.s300.version is None
        # update method in a thread has not been tried to start
        assert m_start.called is False
        # been trying to find the s300 10 times
        assert m_find.call_count == 10

    @pytest.mark.parametrize(
        "version, read_calls, write_calls",
        (
            (
                constants.S3003_ID,
                [
                    call.read(0x82, 1000, 1000),
                    call.read(0x82, 128, 1000),
                    call.read(0x82, 1000),
                ],
                [
                    call.write(b"\x90"),
                    call.write(b"\xB0"),
                    call.write(b"\x40"),
                ],
            ),
            (
                None,
                [
                    call.read(0x82, 1000, 1000),
                    call.read(0x82, 128, 1000),
                    call.read(0x82, 1000),
                ],
                [
                    call.write(b"\x90"),
                    call.write(b"\xB0"),
                    call.write(b"\x40"),
                ],
            ),
        ),
    )
    def test__read_from_device(self, version, read_calls, write_calls):
        device = MagicMock()
        device.read = MagicMock(return_value=[])
        entry_point = MagicMock()

        assert ([], [],
                []) == self.s300._read_from_device(version, device,
                                                   entry_point)
        assert device.mock_calls == read_calls
        assert entry_point.mock_calls == write_calls

    def test_find_and_connect_exception(self):
        """usb exception should be caught and retry device connection MAX_CONNECTION_RETRIES times"""
        self.s300.status = False
        with mock.patch("threading.Thread.start") as m_start, mock.patch(
                "backend.devices.s300.s300.establish_connection"
        ) as m_establish_connection, mock.patch(
                "backend.devices.s300.s300.find_device") as m_find_device:
            m_establish_connection.side_effect = usb.core.USBError("foo")
            m_find_device.return_value = (MagicMock(), None)
            self.s300.find_and_connect()
        assert self.s300.status is False
        assert m_establish_connection.call_count == MAX_CONNECTION_RETRIES
        assert m_start.called is False

    @pytest.mark.parametrize(
        "error, status_result, init_called_result",
        ((usb.core.USBError("foo"), False, True),
         # "(usb.core.USBError("foo", errno=60), True, False)
         ),
    )
    def test__update_excption(self, error, status_result, init_called_result):
        """in case any usb error while fetching the data"""
        self.s300.status = True
        self.s300.version = self.s300.device = self.s300.entry_point = None
        with mock.patch(
                "backend.devices.s300.s300.S300._read_from_device"
        ) as m__read_from_device, mock.patch(
                "backend.devices.s300.s300.S300.__init__") as m___init__:
            m__read_from_device.side_effect = error
            self.s300._update()
        assert self.s300.status is status_result
        assert m___init__.called is init_called_result

    def test_eth(self):
        self.s300.version = constants.S3003_ID
        self.s300.data5[constants.S3003_ETH] = 50

        assert self.s300.eth == 50

    def test_flt(self):
        self.s300.version = constants.S3003_ID
        self.s300.data5[constants.S3003_FLT] = 50

        assert self.s300.flt == {"celsius": 10, "fahrenheit": 50.0}

    def test_bat(self):
        self.s300.version = constants.S3003_ID
        self.s300.data6[constants.S3003_BAT] = 12.4

        assert self.s300.bat == 0.7400000000000002

    @pytest.mark.parametrize(
        "value, result",
        (
            (25, 0),
            (255, 115),
        ),
    )
    def test_tps(self, value, result):
        self.s300.version = constants.S3003_ID
        self.s300.data6[constants.S3003_TPS] = value

        assert self.s300.tps == result

    def test_gear(self):
        self.s300.version = constants.S3003_ID
        self.s300.data6[constants.S3003_GEAR] = 1

        assert self.s300.gear == 1

    @pytest.mark.parametrize(
        "value, result",
        (
            (0, False),
            (128, True),
        ),
    )
    def test_fanc(self, value, result):
        self.s300.version = constants.S3003_ID
        self.s300.data6[constants.S3003_FANC] = value

        assert self.s300.fanc == result

    def test_rpm(self):
        self.s300.version = constants.S3003_ID
        self.s300.data6[constants.S3003_RPM1] = 100
        self.s300.data6[constants.S3003_RPM2] = 100

        assert self.s300.rpm == 25700

    @pytest.mark.parametrize(
        "version, index1, index2, value1, value2, result",
        (
            (
                constants.S3003_ID,
                constants.S3003_VSS1,
                constants.S3003_VSS2,
                220,
                8,
                {
                    "kmh": 100,
                    "mph": 62
                },
            ),
            (
                constants.S3003_ID,
                constants.S3003_VSS1,
                constants.S3003_VSS2,
                0,
                0,
                {
                    "kmh": 0,
                    "mph": 0
                },
            ),
        ),
    )
    def test_vss(self, version, index1, index2, value1, value2, result):
        self.s300.version = version
        self.s300.data6[index1] = value1
        self.s300.data6[index2] = value2

        assert self.s300.vss == result

    def test_o2(self):
        self.s300.version = constants.S3003_ID
        self.s300.data6[constants.S3003_AFR] = 128

        assert self.s300.o2 == {
            "afr": 14.757147922437671,
            "lambda": 1.0038876137712702
        }

    @pytest.mark.parametrize(
        "version, index, values",
        (
            (None, 0, (None, 0, 0)),
            (constants.S3003_ID, constants.S3003_ECT,
             temp_sensor_argvalues[0]),
            (constants.S3003_ID, constants.S3003_ECT,
             temp_sensor_argvalues[1]),
            (constants.S3003_ID, constants.S3003_ECT,
             temp_sensor_argvalues[2]),
            (constants.S3003_ID, constants.S3003_ECT,
             temp_sensor_argvalues[0]),
            (constants.S3003_ID, constants.S3003_ECT,
             temp_sensor_argvalues[1]),
            (constants.S3003_ID, constants.S3003_ECT,
             temp_sensor_argvalues[2]),
        ),
    )
    def test_ect(self, version, index, values):
        self.s300.version = version
        self.s300.data6[index] = values[0]

        assert self.s300.ect["celsius"] == values[1]
        assert self.s300.ect["fahrenheit"] == values[2]

    @pytest.mark.parametrize(
        "version, index, values",
        (
            (None, 0, (None, 0, 0)),
            (constants.S3003_ID, constants.S3003_IAT,
             temp_sensor_argvalues[0]),
            (constants.S3003_ID, constants.S3003_IAT,
             temp_sensor_argvalues[1]),
            (constants.S3003_ID, constants.S3003_IAT,
             temp_sensor_argvalues[2]),
            (constants.S3003_ID, constants.S3003_IAT,
             temp_sensor_argvalues[0]),
            (constants.S3003_ID, constants.S3003_IAT,
             temp_sensor_argvalues[1]),
            (constants.S3003_ID, constants.S3003_IAT,
             temp_sensor_argvalues[2]),
        ),
    )
    def test_iat(self, version, index, values):
        self.s300.version = version
        self.s300.data6[index] = values[0]

        assert self.s300.iat["celsius"] == values[1]
        assert self.s300.iat["fahrenheit"] == values[2]

    @pytest.mark.parametrize(
        "channel, result",
        (
            (0, 0),
            (1, 0),
            (2, 0),
            (3, 0),
            (4, 0),
            (5, 0),
            (6, 0),
            (7, 0),
        ),
    )
    def test_analog(self, channel, result):
        self.s300.version = constants.S3003_ID

        assert self.s300.analog_input(channel) == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, constants.S3003_MIL, None, False),
            (constants.S3003_ID, constants.S3003_MIL, 0, False),
            (constants.S3003_ID, constants.S3003_MIL, 32, True),
        ),
    )
    def test_mil(self, version, index, value, result):
        self.s300.version = version
        self.s300.data6[index] = value

        assert self.s300.mil == result

    @pytest.mark.parametrize(
        "version, index1, index2, value1, value2, result",
        ((
            constants.S3003_ID,
            constants.S3003_MAP1,
            constants.S3003_MAP2,
            100,
            0,
            {
                "bar": 1.0,
                "mbar": 1000.0,
                "psi": 14.503773773
            },
        ), ),
    )
    def test_map(self, version, index1, index2, value1, value2, result):
        self.s300.version = version
        self.s300.data6[index1] = value1
        self.s300.data6[index2] = value2

        assert self.s300.map == result

    @pytest.mark.parametrize(
        "version, index1, index2, value1, value2, result",
        ((
            constants.S3003_ID,
            constants.S3003_SERIAL1,
            constants.S3003_SERIAL2,
            210,
            4,
            1234,
        ), ),
    )
    def test_serial(self, version, index1, index2, value1, value2, result):
        self.s300.version = version
        self.s300.data4[index1] = value1
        self.s300.data4[index2] = value2

        assert self.s300.serial == result

    @pytest.mark.parametrize(
        "version, index1, index2, value1, value2, result",
        ((
            constants.S3003_ID,
            constants.S3003_FIRM1,
            constants.S3003_FIRM2,
            10,
            0,
            "10.00",
        ), ),
    )
    def test_firmware(self, version, index1, index2, value1, value2, result):
        self.s300.version = version
        self.s300.data4[index1] = value1
        self.s300.data4[index2] = value2

        assert self.s300.firmware == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, 0, None, False),
            (constants.S3003_ID, constants.S3003_SCS, 0, False),
            (constants.S3003_ID, constants.S3003_SCS, 16, True),
        ),
    )
    def test_scs(self, version, index, value, result):
        self.s300.version = version
        self.s300.data6[index] = value

        assert self.s300.scs == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, 0, None, False),
            (constants.S3003_ID, constants.S3003_BKSW, 0, False),
            (constants.S3003_ID, constants.S3003_BKSW, 2, True),
        ),
    )
    def test_bksw(self, version, index, value, result):
        self.s300.version = version
        self.s300.data6[index] = value

        assert self.s300.bksw == result
コード例 #7
0
class TestKpro:

    temp_sensor_argvalues = ((51, 69, 156), (40, 80, 175), (31, 91, 195))

    def setup_method(self):
        # we are not unit testing USB features so it may raise a
        # `usb.core.NoBackendError` e.g. on Docker
        with mock.patch(
                "backend.devices.kpro.kpro.Kpro.__init__") as m___init__:
            m___init__.return_value = None
            self.kpro = Kpro()
        self.kpro.data0 = [None for _ in range(38)]
        self.kpro.data1 = [None for _ in range(7)]
        self.kpro.data3 = [None for _ in range(100)]
        self.kpro.data4 = [None for _ in range(18)]
        self.kpro.data5 = [None for _ in range(20)]

    def test_init(self):
        with mock.patch("usb.core.find"), mock.patch(
                "threading.Thread.start") as m_start:
            self.kpro = Kpro()

        assert self.kpro.status is True
        # update method in a thread has been tried to start
        assert m_start.called is True

    @pytest.mark.parametrize(
        "kpro_version, kpro_vendor_id, kpro_product_id",
        (
            (
                constants.KPRO23_ID,
                constants.KPRO23_ID_VENDOR,
                constants.KPRO23_ID_PRODUCT,
            ),
            (constants.KPRO4_ID, constants.KPRO4_ID_VENDOR,
             constants.KPRO4_ID_PRODUCT),
        ),
    )
    def test_init_with_all_kpro_versions(self, kpro_version, kpro_vendor_id,
                                         kpro_product_id):
        def found_device(idVendor, idProduct):
            if idVendor == kpro_vendor_id and idProduct == kpro_product_id:
                return MagicMock()
            else:
                return None

        with mock.patch("usb.core.find") as m_find, mock.patch(
                "threading.Thread.start") as m_start:
            m_find.side_effect = found_device
            self.kpro = Kpro()

        assert self.kpro.status is True
        # update method in a thread has been tried to start
        assert m_start.called is True
        assert self.kpro.version == kpro_version

    def test_init_no_kpro_connected(self):
        with mock.patch("usb.core.find") as m_find, mock.patch(
                "threading.Thread.start") as m_start:
            m_find.return_value = None
            self.kpro = Kpro()

        assert self.kpro.status is False
        assert self.kpro.version is None
        # update method in a thread has not been tried to start
        assert m_start.called is False
        # been trying to find the two kpro versions per 10 times, so 20 times calling usb find method
        assert m_find.call_count == 20

    @pytest.mark.parametrize(
        "version, read_calls, write_calls",
        (
            (
                constants.KPRO4_ID,
                [
                    call.read(0x82, 1000),
                    call.read(0x82, 1000),
                    call.read(0x82, 1000),
                    call.read(0x82, 1000),
                    call.read(0x82, 128, 1000),
                ],
                [
                    call.write("\x40"),
                    call.write("\x60"),
                    call.write("\x61"),
                    call.write("\x62"),
                    call.write("\x65"),
                ],
            ),
            (
                constants.KPRO23_ID,
                [
                    call.read(0x81, 1000),
                    call.read(0x81, 1000),
                    call.read(0x81, 1000),
                    call.read(0x81, 1000),
                    call.read(0x81, 1000),
                ],
                [
                    call.write("\x40"),
                    call.write("\x60"),
                    call.write("\x61"),
                    call.write("\x62"),
                    call.write("\xb0"),
                ],
            ),
            (
                None,
                [call.read(0x81, 1000),
                 call.read(0x81, 1000)],
                [
                    call.write("\x40"),
                    call.write("\x60"),
                    call.write("\x61"),
                    call.write("\x62"),
                    call.write("\xb0"),
                ],
            ),
        ),
    )
    def test__read_from_device(self, version, read_calls, write_calls):
        device = MagicMock()
        device.read = MagicMock(return_value=[])
        entry_point = MagicMock()

        assert ([], [], [], [], [],
                []) == self.kpro._read_from_device(version, device,
                                                   entry_point)
        assert device.mock_calls == read_calls
        assert entry_point.mock_calls == write_calls

    def test_find_and_connect_exception(self):
        """usb exception should be caught and retry device connection MAX_CONNECTION_RETRIES times"""
        self.kpro.status = False
        with mock.patch("threading.Thread.start") as m_start, mock.patch(
                "backend.devices.kpro.kpro.establish_connection"
        ) as m_establish_connection, mock.patch(
                "backend.devices.kpro.kpro.find_device") as m_find_device:
            m_establish_connection.side_effect = usb.core.USBError("foo")
            m_find_device.return_value = (MagicMock(), None)
            self.kpro.find_and_connect()
        assert self.kpro.status is False
        assert m_establish_connection.call_count == MAX_CONNECTION_RETRIES
        assert m_start.called is False

    @pytest.mark.parametrize(
        "error, status_result, init_called_result",
        ((usb.core.USBError("foo"), False, True),
         # "(usb.core.USBError("foo", errno=60), True, False)
         ),
    )
    def test__update_excption(self, error, status_result, init_called_result):
        """in case any usb error while fetching the data"""
        self.kpro.status = True
        self.kpro.version = self.kpro.kpro_device = self.kpro.entry_point = None
        with mock.patch(
                "backend.devices.kpro.kpro.Kpro._read_from_device"
        ) as m__read_from_device, mock.patch(
                "backend.devices.kpro.kpro.Kpro.__init__") as m___init__:
            m__read_from_device.side_effect = error
            self.kpro._update()
        assert self.kpro.status is status_result
        assert m___init__.called is init_called_result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, 0, 666, 0),
            (constants.KPRO23_ID, constants.KPRO23_BAT, 123, 12.3),
            (constants.KPRO4_ID, constants.KPRO4_BAT, 123, 12.3),
        ),
    )
    def test_bat(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data1[index] = value

        assert self.kpro.bat == result

    def test_eth(self):
        self.kpro.version = constants.KPRO4_ID
        self.kpro.data3[constants.KPRO4_ETH] = 50

        assert self.kpro.eth == 50

    def test_flt(self):
        self.kpro.version = constants.KPRO4_ID
        self.kpro.data3[constants.KPRO4_FLT] = 50

        assert self.kpro.flt == {"celsius": 50, "fahrenheit": 122.0}

    @pytest.mark.parametrize(
        "version, index1, index2, value1, value2, result",
        (
            (
                constants.KPRO23_ID,
                constants.KPRO23_RPM1,
                constants.KPRO23_RPM2,
                100,
                100,
                6425,
            ),
            (
                constants.KPRO4_ID,
                constants.KPRO4_RPM1,
                constants.KPRO4_RPM2,
                100,
                100,
                6425,
            ),
        ),
    )
    def test_rpm(self, version, index1, index2, value1, value2, result):
        self.kpro.version = version
        self.kpro.data0[index1] = value1
        self.kpro.data0[index2] = value2

        assert self.kpro.rpm == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (constants.KPRO23_ID, constants.KPRO23_TPS, 100, 37),
            (constants.KPRO4_ID, constants.KPRO4_TPS, 100, 37),
            (None, constants.KPRO4_TPS, 666, 0),
        ),
    )
    def test_tps(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.tps == result

    @pytest.mark.parametrize(
        "version, index1, index2, value1, value2, result_afr, result_lambda",
        (
            (
                constants.KPRO23_ID,
                constants.KPRO23_AFR1,
                constants.KPRO23_AFR2,
                0,
                128,
                14.7,
                1,
            ),
            (
                constants.KPRO4_ID,
                constants.KPRO4_AFR1,
                constants.KPRO4_AFR2,
                0,
                128,
                14.7,
                1,
            ),
            (
                constants.KPRO4_ID,
                constants.KPRO4_AFR1,
                constants.KPRO4_AFR2,
                0,
                0,
                0,
                0,
            ),
            (
                None,
                0,
                0,
                666,
                666,
                0,
                0,
            ),
        ),
    )
    def test_o2(self, version, index1, index2, value1, value2, result_afr,
                result_lambda):
        self.kpro.version = version
        self.kpro.data0[index1] = value1
        self.kpro.data0[index2] = value2

        assert self.kpro.o2["afr"] == result_afr
        assert self.kpro.o2["lambda"] == result_lambda

    @pytest.mark.parametrize(
        "version, index, value, result_kmh, result_mph",
        (
            (None, 0, None, 0, 0),
            (constants.KPRO23_ID, constants.KPRO23_VSS, 100, 100, 62),
            (constants.KPRO4_ID, constants.KPRO4_VSS, 100, 100, 62),
        ),
    )
    def test_vss(self, version, index, value, result_kmh, result_mph):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.vss["kmh"] == result_kmh
        assert self.kpro.vss["mph"] == result_mph

    @pytest.mark.parametrize(
        "version, index, values",
        (
            (None, 0, (None, 0, 0)),
            (constants.KPRO23_ID, constants.KPRO23_ECT,
             temp_sensor_argvalues[0]),
            (constants.KPRO23_ID, constants.KPRO23_ECT,
             temp_sensor_argvalues[1]),
            (constants.KPRO23_ID, constants.KPRO23_ECT,
             temp_sensor_argvalues[2]),
            (constants.KPRO4_ID, constants.KPRO4_ECT,
             temp_sensor_argvalues[0]),
            (constants.KPRO4_ID, constants.KPRO4_ECT,
             temp_sensor_argvalues[1]),
            (constants.KPRO4_ID, constants.KPRO4_ECT,
             temp_sensor_argvalues[2]),
        ),
    )
    def test_ect(self, version, index, values):
        self.kpro.version = version
        self.kpro.data1[index] = values[0]

        assert self.kpro.ect["celsius"] == values[1]
        assert self.kpro.ect["fahrenheit"] == values[2]

    @pytest.mark.parametrize(
        "version, index, values",
        (
            (None, 0, (None, 0, 0)),
            (constants.KPRO23_ID, constants.KPRO23_IAT,
             temp_sensor_argvalues[0]),
            (constants.KPRO23_ID, constants.KPRO23_IAT,
             temp_sensor_argvalues[1]),
            (constants.KPRO23_ID, constants.KPRO23_IAT,
             temp_sensor_argvalues[2]),
            (constants.KPRO4_ID, constants.KPRO4_IAT,
             temp_sensor_argvalues[0]),
            (constants.KPRO4_ID, constants.KPRO4_IAT,
             temp_sensor_argvalues[1]),
            (constants.KPRO4_ID, constants.KPRO4_IAT,
             temp_sensor_argvalues[2]),
        ),
    )
    def test_iat(self, version, index, values):
        self.kpro.version = version
        self.kpro.data1[index] = values[0]

        assert self.kpro.iat["celsius"] == values[1]
        assert self.kpro.iat["fahrenheit"] == values[2]

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, 0, 100, (0, 0, 0)),
            (constants.KPRO23_ID, constants.KPRO23_MAP, 100,
             (1, 1000, 14.503773773)),
            (constants.KPRO4_ID, constants.KPRO4_MAP, 100,
             (1, 1000, 14.503773773)),
        ),
    )
    def test_map(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.map["bar"] == result[0]
        assert self.kpro.map["mbar"] == result[1]
        assert self.kpro.map["psi"] == result[2]

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (constants.KPRO23_ID, constants.KPRO23_CAM, 100, 30.0),
            (constants.KPRO4_ID, constants.KPRO4_CAM, 100, 30.0),
        ),
    )
    def test_cam(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.cam == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (constants.KPRO23_ID, constants.KPRO23_GEAR, 1, 1),
            (constants.KPRO4_ID, constants.KPRO4_GEAR, 1, 1),
        ),
    )
    def test_gear(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.gear == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, 0, None, False),
            (constants.KPRO23_ID, constants.KPRO23_EPS, 0, False),
            (constants.KPRO23_ID, constants.KPRO23_EPS, 32, True),
            (constants.KPRO4_ID, constants.KPRO4_EPS, 0, False),
            (constants.KPRO4_ID, constants.KPRO4_EPS, 32, True),
        ),
    )
    def test_eps(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.eps == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, 0, None, False),
            (constants.KPRO23_ID, constants.KPRO23_SCS, 0, False),
            (constants.KPRO23_ID, constants.KPRO23_SCS, 16, True),
            (constants.KPRO4_ID, constants.KPRO4_SCS, 0, False),
            (constants.KPRO4_ID, constants.KPRO4_SCS, 16, True),
        ),
    )
    def test_scs(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.scs == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, 0, None, False),
            (constants.KPRO23_ID, constants.KPRO23_RVSLCK, 0, False),
            (constants.KPRO23_ID, constants.KPRO23_RVSLCK, 1, True),
            (constants.KPRO4_ID, constants.KPRO4_RVSLCK, 0, False),
            (constants.KPRO4_ID, constants.KPRO4_RVSLCK, 1, True),
        ),
    )
    def test_rvslck(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.rvslck == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, 0, None, False),
            (constants.KPRO23_ID, constants.KPRO23_BKSW, 0, False),
            (constants.KPRO23_ID, constants.KPRO23_BKSW, 2, True),
            (constants.KPRO4_ID, constants.KPRO4_BKSW, 0, False),
            (constants.KPRO4_ID, constants.KPRO4_BKSW, 2, True),
        ),
    )
    def test_bksw(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.bksw == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (constants.KPRO23_ID, constants.KPRO23_ACSW, 0, False),
            (constants.KPRO23_ID, constants.KPRO23_ACSW, 4, True),
            (constants.KPRO4_ID, constants.KPRO4_ACSW, 0, False),
            (constants.KPRO4_ID, constants.KPRO4_ACSW, 4, True),
        ),
    )
    def test_acsw(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.acsw == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (constants.KPRO23_ID, constants.KPRO23_ACCL, 0, False),
            (constants.KPRO23_ID, constants.KPRO23_ACCL, 8, True),
            (constants.KPRO4_ID, constants.KPRO4_ACCL, 0, False),
            (constants.KPRO4_ID, constants.KPRO4_ACCL, 8, True),
        ),
    )
    def test_accl(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.accl == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (constants.KPRO23_ID, constants.KPRO23_FLR, 0, False),
            (constants.KPRO23_ID, constants.KPRO23_FLR, 64, True),
            (constants.KPRO4_ID, constants.KPRO4_FLR, 0, False),
            (constants.KPRO4_ID, constants.KPRO4_FLR, 64, True),
        ),
    )
    def test_flr(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.flr == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (constants.KPRO23_ID, constants.KPRO23_FANC, 0, False),
            (constants.KPRO23_ID, constants.KPRO23_FANC, 128, True),
            (constants.KPRO4_ID, constants.KPRO4_FANC, 0, False),
            (constants.KPRO4_ID, constants.KPRO4_FANC, 128, True),
        ),
    )
    def test_fanc(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data0[index] = value

        assert self.kpro.fanc == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, None, None, False),
            (constants.KPRO23_ID, constants.KPRO23_MIL, 0, False),
            (constants.KPRO23_ID, constants.KPRO23_MIL, 9, True),
            (constants.KPRO4_ID, constants.KPRO4_MIL, 0, False),
            (constants.KPRO4_ID, constants.KPRO4_MIL, 36, True),
        ),
    )
    def test_mil(self, version, index, value, result):
        self.kpro.version = version
        if version == constants.KPRO23_ID:
            self.kpro.data0[index] = value
        elif version == constants.KPRO4_ID:
            self.kpro.data3[index] = value

        assert self.kpro.mil == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (constants.KPRO23_ID, constants.KPRO23_ECU_TYPE, 3, "RSX - PRB"),
            (constants.KPRO23_ID, constants.KPRO23_ECU_TYPE, 0, "unknown"),
            (constants.KPRO4_ID, constants.KPRO4_ECU_TYPE, 3, "RSX - PRB"),
            (constants.KPRO4_ID, constants.KPRO4_ECU_TYPE, 0, "unknown"),
        ),
    )
    def test_ecu_type(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data4[index] = value

        assert self.kpro.ecu_type == result

    @pytest.mark.parametrize(
        "version, index, value, result",
        (
            (None, 0, None, False),
            (constants.KPRO23_ID, constants.KPRO23_IGN, 0, False),
            (constants.KPRO23_ID, constants.KPRO23_IGN, 1, True),
            (constants.KPRO4_ID, constants.KPRO4_IGN, 0, False),
            (constants.KPRO4_ID, constants.KPRO4_IGN, 1, True),
        ),
    )
    def test_ign(self, version, index, value, result):
        self.kpro.version = version
        self.kpro.data4[index] = value

        assert self.kpro.ign == result

    @pytest.mark.parametrize(
        "version, index1, index2, value1, value2, result",
        (
            (
                constants.KPRO23_ID,
                constants.KPRO23_SERIAL1,
                constants.KPRO23_SERIAL2,
                210,
                4,
                1234,
            ),
            (
                constants.KPRO4_ID,
                constants.KPRO4_SERIAL1,
                constants.KPRO4_SERIAL2,
                210,
                4,
                1234,
            ),
        ),
    )
    def test_serial(self, version, index1, index2, value1, value2, result):
        self.kpro.version = version
        self.kpro.data4[index1] = value1
        self.kpro.data4[index2] = value2

        assert self.kpro.serial == result

    @pytest.mark.parametrize(
        "index1, index2, value1, value2, channel, result",
        (
            (constants.KPRO4_AN0_1, constants.KPRO4_AN0_2, 3, 52, 0,
             1.0009765625),
            (constants.KPRO4_AN1_1, constants.KPRO4_AN1_2, 3, 52, 1,
             1.0009765625),
            (constants.KPRO4_AN2_1, constants.KPRO4_AN2_2, 3, 52, 2,
             1.0009765625),
            (constants.KPRO4_AN3_1, constants.KPRO4_AN3_2, 3, 52, 3,
             1.0009765625),
            (constants.KPRO4_AN4_1, constants.KPRO4_AN4_2, 3, 52, 4,
             1.0009765625),
            (constants.KPRO4_AN5_1, constants.KPRO4_AN5_2, 3, 52, 5,
             1.0009765625),
            (constants.KPRO4_AN6_1, constants.KPRO4_AN6_2, 3, 52, 6,
             1.0009765625),
            (constants.KPRO4_AN7_1, constants.KPRO4_AN7_2, 3, 52, 7,
             1.0009765625),
        ),
    )
    def test_analog_input_v4(self, index1, index2, value1, value2, channel,
                             result):
        self.kpro.version = constants.KPRO4_ID
        self.kpro.data3[index2] = value2
        self.kpro.data3[index1] = value1

        assert self.kpro.analog_input(channel) == result

    @pytest.mark.parametrize(
        "index1, index2, value1, value2, channel, result",
        (
            (constants.KPRO3_AN0_1, constants.KPRO3_AN0_2, 3, 52, 0,
             4.00390625),
            (constants.KPRO3_AN1_1, constants.KPRO3_AN1_2, 3, 52, 1,
             4.00390625),
            (constants.KPRO3_AN2_1, constants.KPRO3_AN2_2, 3, 52, 2,
             4.00390625),
            (constants.KPRO3_AN3_1, constants.KPRO3_AN3_2, 3, 52, 3,
             4.00390625),
            (constants.KPRO3_AN4_1, constants.KPRO3_AN4_2, 3, 52, 4,
             4.00390625),
            (constants.KPRO3_AN5_1, constants.KPRO3_AN5_2, 3, 52, 5,
             4.00390625),
            (constants.KPRO3_AN6_1, constants.KPRO3_AN6_2, 3, 52, 6,
             4.00390625),
            (constants.KPRO3_AN7_1, constants.KPRO3_AN7_2, 3, 52, 7,
             4.00390625),
        ),
    )
    def test_analog_input_v3(self, index1, index2, value1, value2, channel,
                             result):
        self.kpro.version = constants.KPRO23_ID
        self.kpro.data5[index2] = value2
        self.kpro.data5[index1] = value1

        assert self.kpro.analog_input(channel) == result

    @pytest.mark.parametrize(
        "channel, result",
        (
            (0, 0),
            (1, 0),
            (2, 0),
            (3, 0),
            (4, 0),
            (5, 0),
            (6, 0),
            (7, 0),
        ),
    )
    def test_analog_input_no_version(self, channel, result):
        self.kpro.version = None

        assert self.kpro.analog_input(channel) == result