Skip to content

Commit

Permalink
Merge branch 'main' into database-api
Browse files Browse the repository at this point in the history
  • Loading branch information
mdabrowski1990 authored Dec 6, 2024
2 parents 8bd4691 + 8a6b3f8 commit 0f9642f
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ def test_name(self):
self.mock_data_record._AbstractDataRecord__name = Mock()
assert AbstractDataRecord.name.fget(self.mock_data_record) == self.mock_data_record._AbstractDataRecord__name

def test_data_record_type(self):
self.mock_data_record.__class__.__name__ = "MockDataRecord"
assert AbstractDataRecord.data_record_type.fget(self.mock_data_record) == "MockDataRecord"
# max_raw_value

@pytest.mark.parametrize(
"length, value", [
(2, 3),
(5, 31),
(8, 255),
]
)
def test_max_raw_value_getter(self, length, value):
self.mock_data_record.length = length
assert AbstractDataRecord.max_raw_value.fget(self.mock_data_record) == value
167 changes: 120 additions & 47 deletions tests/software_tests/database/data_record/test_raw_data_record.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
from mock import patch
from mock import Mock, patch

from uds.database.data_record.raw_data_record import RawDataRecord

Expand All @@ -9,80 +9,153 @@
class TestRawDataRecord:

def setup_method(self):
self.name = "TestRawDataRecord"
self.length = 8
self.raw_data_record = RawDataRecord(self.name, self.length)
self.mock_data_record = Mock(spec=RawDataRecord)

# __init__

def test_init_valid(self):
assert self.raw_data_record.name == self.name
assert self.raw_data_record.length == self.length

def test_init_type_error_for_name(self):
with pytest.raises(TypeError):
RawDataRecord(123, self.length)

def test_init_value_error_for_length(self):
with pytest.raises(ValueError):
RawDataRecord(self.name, -5)

def test_init_type_error_for_length(self):
with pytest.raises(TypeError):
RawDataRecord(self.name, "eight")
@pytest.mark.parametrize(
"name, length", [
("TestRawDataRecord", 8),
(Mock(), Mock()),
]
)
@patch(f"{SCRIPT_LOCATION}.AbstractDataRecord.__init__")
def test_init__valid(self, mock_abstract, name, length):
assert RawDataRecord.__init__(self.mock_data_record, name, length) is None
mock_abstract.assert_called_once_with(name)
assert self.mock_data_record.length == length

# length

def test_length_getter(self):
assert self.raw_data_record.length == self.length

def test_length_setter_valid(self):
self.raw_data_record.length = 16
assert self.raw_data_record.length == 16

def test_length_setter_type_error(self):
self.mock_data_record._RawDataRecord__length = Mock()
assert RawDataRecord.length.fget(self.mock_data_record) == self.mock_data_record._RawDataRecord__length

@pytest.mark.parametrize(
"value", [1, 8]
)
def test_length_setter_valid(self, value):
RawDataRecord.length.fset(self.mock_data_record, value)
assert self.mock_data_record._RawDataRecord__length == value

@pytest.mark.parametrize(
"value", ["test", None]
)
@patch(f"{SCRIPT_LOCATION}.isinstance")
def test_length_setter_type_error(self, mock_isinstance, value):
mock_isinstance.return_value = False
with pytest.raises(TypeError):
self.raw_data_record.length = "sixteen"
RawDataRecord.length.fset(self.mock_data_record, value)
mock_isinstance.assert_called_once_with(value, int)

def test_length_setter_value_error(self):
@pytest.mark.parametrize(
"value", [0, -1]
)
def test_length_setter_value_error(self, value):
with pytest.raises(ValueError):
self.raw_data_record.length = -10
RawDataRecord.length.fset(self.mock_data_record, value)

# max_raw_value

@pytest.mark.parametrize(
"length, value", [
(2, 3),
(5, 31),
(8, 255),
]
)
def test_max_raw_value_getter(self, length, value):
raw_data_record = RawDataRecord("TestRawDataRecord", length)
assert raw_data_record.max_raw_value == value

# is_reoccurring

def test_is_reoccurring(self):
assert self.raw_data_record.is_reoccurring is False
def test_is_reoccurring_getter(self):
assert RawDataRecord.is_reoccurring.fget(self.mock_data_record) is False

# min_occurrences

def test_min_occurrences(self):
assert self.raw_data_record.min_occurrences == 1
def test_min_occurrences_getter(self):
assert RawDataRecord.min_occurrences.fget(self.mock_data_record) == 1

# max_occurrences

def test_max_occurrences(self):
assert self.raw_data_record.max_occurrences == 1
def test_max_occurrences_getter(self):
assert RawDataRecord.max_occurrences.fget(self.mock_data_record) == 1

# contains

def test_contains(self):
assert self.raw_data_record.contains == ()
def test_contains_getter(self):
assert RawDataRecord.contains.fget(self.mock_data_record) == ()

# decode

@pytest.mark.parametrize(
"value", [1, 4]
)
@patch(f"{SCRIPT_LOCATION}.DecodedDataRecord")
def test_decode(self, mock_decoded_data_record):
raw_value = 42
result = self.raw_data_record.decode(raw_value)
def test_decode(self, mock_decoded_data_record, value):
self.mock_data_record.max_raw_value = 8
assert RawDataRecord.decode(self.mock_data_record, value) == mock_decoded_data_record.return_value
mock_decoded_data_record.assert_called_once_with(
name=self.name,
raw_value=raw_value,
physical_value=raw_value
name=self.mock_data_record.name,
raw_value=value,
physical_value=value
)
assert result == mock_decoded_data_record.return_value

@pytest.mark.parametrize(
"value", ["test", None]
)
@patch(f"{SCRIPT_LOCATION}.isinstance")
def test_decode_type_error(self, mock_isinstance, value):
mock_isinstance.return_value = False
with pytest.raises(TypeError):
RawDataRecord.decode(self.mock_data_record, value)
mock_isinstance.assert_called_once_with(value, int)

@pytest.mark.parametrize(
"value, max_raw_value", [
(-1, 2),
(3, 2),
(16, 6),
]
)
def test_decode_value_error(self, value, max_raw_value):
self.mock_data_record.max_raw_value = max_raw_value
with pytest.raises(ValueError):
RawDataRecord.decode(self.mock_data_record, value)

# encode

def test_encode(self):
physical_value = 42
assert self.raw_data_record.encode(physical_value) == physical_value
@pytest.mark.parametrize(
"value, max_raw_value", [
(0, 2),
(3, 3),
(16, 16),
]
)
def test_encode(self, value, max_raw_value):
self.mock_data_record.max_raw_value = max_raw_value
assert RawDataRecord.encode(self.mock_data_record, value) == value

@pytest.mark.parametrize(
"value", ["test", None]
)
@patch(f"{SCRIPT_LOCATION}.isinstance")
def test_encode_type_error(self, mock_isinstance, value):
mock_isinstance.return_value = False
with pytest.raises(TypeError):
RawDataRecord.encode(self.mock_data_record, value)
mock_isinstance.assert_called_once_with(value, int)

@pytest.mark.parametrize(
"value, max_raw_value", [
(-1, 2),
(3, 2),
(16, 6),
]
)
def test_encode_value_error(self, value, max_raw_value):
self.mock_data_record.max_raw_value = max_raw_value
with pytest.raises(ValueError):
RawDataRecord.encode(self.mock_data_record, value)
2 changes: 0 additions & 2 deletions uds/database/data_record/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,5 @@
meaningful information (e.g. physical value, text).
"""

__all__ = ["AbstractDataRecord", "DecodedDataRecord", "RawDataRecord"]

from .abstract_data_record import AbstractDataRecord, DecodedDataRecord
from .raw_data_record import RawDataRecord
14 changes: 9 additions & 5 deletions uds/database/data_record/abstract_data_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,20 @@ def name(self) -> str:
"""Name of this Data Record."""
return self.__name

@property # noqa: F841
def data_record_type(self) -> str:
"""Type of this Data Record."""
return self.__class__.__name__

@property # noqa: F841
@abstractmethod
def length(self) -> int:
"""Get number of bits that this Data Record is stored over."""

@property
def max_raw_value(self):
"""
Maximum raw (bit) value for this Data Record.
:return: Maximum value that can be represented by `length` bits.
"""
return (1 << self.length) - 1

@property # noqa: F841
@abstractmethod
def is_reoccurring(self) -> bool:
Expand Down
21 changes: 21 additions & 0 deletions uds/database/data_record/raw_data_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,18 @@ def decode(self, raw_value: int) -> DecodedDataRecord:
:param raw_value: Raw (bit) value of Data Record.
:return: Dictionary with physical value for this Data Record.
:raises TypeError: Provided `raw_value` is not int type.
:raises ValueError: Provided `raw_value` is out of range (0 <= raw_value <= max_raw_value).
"""
if not isinstance(raw_value, int):
raise TypeError(f"Expected raw_value to be an int type, got '{type(raw_value).__name__}' instead.")

if not 0 <= raw_value <= self.max_raw_value:
raise ValueError(
"Provided value of raw_value is out of range: "
f"must be between 0 and {self.max_raw_value}, got {raw_value}."
)
return DecodedDataRecord(name=self.name, raw_value=raw_value, physical_value=raw_value)

def encode(self, physical_value: DataRecordPhysicalValueAlias) -> int:
Expand All @@ -99,4 +110,14 @@ def encode(self, physical_value: DataRecordPhysicalValueAlias) -> int:
:return: Raw Value of this Data Record.
"""
if not isinstance(physical_value, int):
raise TypeError(
f"Expected physical_value to be an int type, got '{type(physical_value).__name__}' instead."
)

if not 0 <= physical_value <= self.max_raw_value:
raise ValueError(
"Provided value of physical_value is out of range: "
f"must be between 0 and {self.max_raw_value}, got {physical_value}."
)
return physical_value # type: ignore

0 comments on commit 0f9642f

Please sign in to comment.