319 lines
15 KiB
Python
319 lines
15 KiB
Python
# Copyright 2024 Volvo Car Corporation
|
|
# Licensed under Apache 2.0.
|
|
|
|
"""Module to test the ModelYmlVerification class."""
|
|
|
|
|
|
import unittest
|
|
from unittest import mock
|
|
|
|
from powertrain_build.interface.model_yaml_verification import ModelYmlVerification
|
|
|
|
|
|
class TestModelYamlVerification(unittest.TestCase):
|
|
"""Unit tests for the ModelYmlVerification class."""
|
|
|
|
def test_verify_outsignals(self):
|
|
"""Test the verify_signals method with outsignals."""
|
|
app = mock.MagicMock()
|
|
modelyamlver = ModelYmlVerification(app)
|
|
modelyamlver.model_name = "dummy_model"
|
|
modelyamlver.signal_properties = {"dummy_model": []}
|
|
modelyamlver.app_outsignals = {}
|
|
modelyamlver.raw = {"dummy_dp": [{"property": "test_outsignal", "outsignal": "test_outsignal"}]}
|
|
exception_msg = "ERROR:root:test_outsignal is not defined as an outsignal in json file\n"
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
# Different properties connected to the same outsignal in the same device proxy.
|
|
modelyamlver.app_outsignals = ["test_outsignal"]
|
|
modelyamlver.signal_properties = {"dummy_model": []}
|
|
modelyamlver.raw = {
|
|
"dummy_dp": [
|
|
{"property": "test_property", "outsignal": "test_outsignal"},
|
|
{"property": "test_property2", "outsignal": "test_outsignal"},
|
|
]
|
|
}
|
|
|
|
exception_msg = (
|
|
"ERROR:root:You can't connect a signal test_outsignal in dummy_model model to the same "
|
|
"interface (dummy_dp) twice. It's already connected as "
|
|
"dummy_dp.test_property.test_outsignal in model dummy_model.\n"
|
|
)
|
|
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
# Different properties connected to the same outsignal in different device proxies.
|
|
modelyamlver.app_outsignals = ["test_outsignal"]
|
|
modelyamlver.signal_properties = {"dummy_model": []}
|
|
modelyamlver.raw = {
|
|
"dummy_dp": [
|
|
{"property": "test_property", "outsignal": "test_outsignal"},
|
|
],
|
|
"dummy_dp2": [{"property": "test_property2", "outsignal": "test_outsignal"}],
|
|
}
|
|
|
|
expected_signal_properties = {
|
|
"dummy_model": ["dummy_dp.test_property.test_outsignal", "dummy_dp2.test_property2.test_outsignal"],
|
|
}
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(expected_signal_properties, modelyamlver.signal_properties)
|
|
|
|
# Different properties connected to the same outsignal in different device proxies.
|
|
modelyamlver.app_outsignals = ["test_outsignal2", "test_outsignal"]
|
|
modelyamlver.signal_properties = {"dummy_model": []}
|
|
modelyamlver.raw = {
|
|
"dummy_dp": [
|
|
{"property": "test_property2", "outsignal": "test_outsignal2"},
|
|
{"property": "test_property", "outsignal": "test_outsignal"},
|
|
]
|
|
}
|
|
|
|
expected_signal_properties = {
|
|
"dummy_model": ["dummy_dp.test_property2.test_outsignal2", "dummy_dp.test_property.test_outsignal"],
|
|
}
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(expected_signal_properties, modelyamlver.signal_properties)
|
|
|
|
# Different outsignals connected to the same property
|
|
modelyamlver.app_outsignals = ["test_outsignal", "test_outsignal2"]
|
|
modelyamlver.signal_properties = {"dummy_model": []}
|
|
modelyamlver.raw = {
|
|
"dummy_dp": [
|
|
{"property": "test_property", "outsignal": "test_outsignal"},
|
|
{"property": "test_property", "outsignal": "test_outsignal2"},
|
|
]
|
|
}
|
|
exception_msg = (
|
|
"ERROR:root:You can't connect another signal to the existing property "
|
|
"dummy_dp.test_property.test_outsignal2"
|
|
" in dummy_model model, because it is already defined in dummy_model model.\n"
|
|
)
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
# Same outsignal connected to the same property several times
|
|
modelyamlver.app_outsignals = ["test_outsignal", "test_outsignal2"]
|
|
modelyamlver.signal_properties = {"dummy_model": []}
|
|
modelyamlver.raw = {
|
|
"dummy_dp": [
|
|
{"property": "test_property", "outsignal": "test_outsignal"},
|
|
{"property": "test_property", "outsignal": "test_outsignal"},
|
|
]
|
|
}
|
|
exception_msg = "ERROR:root:You can't connect signal test_outsignal in dummy_model model twice.\n"
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
def test_verify_insignals(self):
|
|
"""Test the verify_signals method with insignals."""
|
|
app = mock.MagicMock()
|
|
modelyamlver = ModelYmlVerification(app)
|
|
modelyamlver.model_name = "dummy_model"
|
|
modelyamlver.app_insignals = {}
|
|
modelyamlver.raw = {"dummy_dp": [{"property": "test_property", "insignal": "test_insignal"}]}
|
|
exception_msg = "ERROR:root:test_insignal is not defined as an insignal in json file\n"
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
# Different properties connected to the same insignal
|
|
modelyamlver.app_insignals = ["test_insignal"]
|
|
modelyamlver.signal_properties = {"dummy_model": []}
|
|
modelyamlver.raw = {
|
|
"dummy_dp": [
|
|
{"property": "test_property", "insignal": "test_insignal"},
|
|
{"property": "test_property2", "insignal": "test_insignal"},
|
|
]
|
|
}
|
|
exception_msg = (
|
|
"ERROR:root:You can't connect a signal test_insignal in dummy_model model to two"
|
|
" different primitives. It's already connected in dummy_model model\n"
|
|
)
|
|
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
# Different insignals connected to the same property
|
|
modelyamlver.app_insignals = ["test_insignal", "test_insignal2"]
|
|
modelyamlver.signal_properties = {"dummy_model": []}
|
|
modelyamlver.raw = {
|
|
"dummy_dp": [
|
|
{"property": "test_property", "insignal": "test_insignal"},
|
|
{"property": "test_property", "insignal": "test_insignal2"},
|
|
]
|
|
}
|
|
exception_msg = (
|
|
"ERROR:root:You can't connect another signal to the existing property "
|
|
"dummy_dp.test_property.test_insignal2"
|
|
" in dummy_model model, because it is already defined in dummy_model model.\n"
|
|
)
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
# Different insignals connected to the same property in different models, should give an error message
|
|
modelyamlver.signal_properties = {"dummy_model": [], "dummy_model2": []}
|
|
modelyamlver.app_insignals = ["test_insignal", "test_insignal2"]
|
|
model_signal = {"dummy_model": "test_insignal", "dummy_model2": "test_insignal2"}
|
|
for model in ["dummy_model", "dummy_model2"]:
|
|
modelyamlver.model_name = model
|
|
modelyamlver.raw = {"dummy_dp": [{"property": "test_property", "insignal": model_signal[model]}]}
|
|
exception_msg = (
|
|
"ERROR:root:You can't connect another signal to the existing property "
|
|
"dummy_dp.test_property.test_insignal2"
|
|
" in dummy_model2 model, because it is already defined in dummy_model model.\n"
|
|
)
|
|
try:
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
except AssertionError:
|
|
warn_info = None
|
|
if not hasattr(warn_info, "output"):
|
|
raise AssertionError("no logs of level INFO or higher triggered on root")
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
# Same insignal connected to the same property several times
|
|
modelyamlver.app_insignals = ["test_insignal", "test_insignal2"]
|
|
modelyamlver.signal_properties = {"dummy_model": []}
|
|
modelyamlver.model_name = "dummy_model"
|
|
modelyamlver.raw = {
|
|
"dummy_dp": [
|
|
{"property": "test_property", "insignal": "test_insignal"},
|
|
{"property": "test_property", "insignal": "test_insignal"},
|
|
]
|
|
}
|
|
exception_msg = "ERROR:root:You can't connect signal test_insignal in dummy_model model twice.\n"
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
# Same insignal connected to the same property in different models, this should not give an error message
|
|
modelyamlver.signal_properties = {"dummy_model": [], "dummy_model2": []}
|
|
modelyamlver.app_insignals = ["test_insignal"]
|
|
for model in ["dummy_model", "dummy_model2"]:
|
|
modelyamlver.model_name = model
|
|
modelyamlver.raw = {"dummy_dp": [{"property": "test_property", "insignal": "test_insignal"}]}
|
|
exception_msg = (
|
|
"ERROR:root:You can't write dummy_dp.test_property in dummy_model2 model."
|
|
" It already exists in dummy_model model\n"
|
|
)
|
|
try:
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
except AssertionError:
|
|
continue
|
|
raise AssertionError(f"Error raised: {warn_info.output}")
|
|
|
|
def test_verify_hal_struct(self):
|
|
"""Test the verify_signals method for hal struct."""
|
|
app = mock.MagicMock()
|
|
modelyamlver = ModelYmlVerification(app)
|
|
modelyamlver.model_name = "dummy_model"
|
|
modelyamlver.app_insignals = {}
|
|
modelyamlver.raw = {
|
|
"insignal_struct": [
|
|
{"insignal": "test_insignal", "property": "test_insignal"},
|
|
{"property": "test_insignal2", "insignal": "test_insignal2"},
|
|
]
|
|
}
|
|
exception_msg = [
|
|
"ERROR:root:test_insignal is not defined as an insignal in json file\n",
|
|
"ERROR:root:test_insignal2 is not defined as an insignal in json file\n",
|
|
]
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw)
|
|
self.assertEqual(warn_info.output, exception_msg)
|
|
|
|
def test_verify_hal_signals(self):
|
|
"""Test the verify_signals method for hal signals."""
|
|
app = mock.MagicMock()
|
|
modelyamlver = ModelYmlVerification(app)
|
|
modelyamlver.model_name = "dummy_model"
|
|
modelyamlver.app_insignals = {}
|
|
modelyamlver.raw = {"insignal_property": [{"insignal": "test_insignal"}]}
|
|
exception_msg = "ERROR:root:test_insignal is not defined as an insignal in json file\n"
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.verify_signals(modelyamlver.raw, is_hal=True, is_service=False, group="dummy_grp")
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
app = mock.MagicMock()
|
|
modelyamlver = ModelYmlVerification(app)
|
|
modelyamlver.model_name = "dummy_model"
|
|
modelyamlver.app_insignals = ["test_insignal"]
|
|
modelyamlver.raw = {"insignal_property": [{"insignal": "test_insignal"}]}
|
|
modelyamlver.signal_properties = {"dummy_model": ["dummy_dp.property_outsignal"]}
|
|
modelyamlver.verify_signals(modelyamlver.raw, is_hal=True, is_service=False, group="dummy_grp")
|
|
expected_signal_properties = {
|
|
"dummy_model": ["dummy_dp.property_outsignal", "insignal_property.dummy_grp.test_insignal"]
|
|
}
|
|
self.assertEqual(modelyamlver.signal_properties, expected_signal_properties)
|
|
|
|
def test_parse_service_definitions(self):
|
|
"""Test the parse_service_definitions method."""
|
|
app = mock.MagicMock()
|
|
modelyamlver = ModelYmlVerification(app)
|
|
modelyamlver.model_name = "dummy_model"
|
|
modelyamlver.app_insignals = ["test_insignal"]
|
|
modelyamlver.signal_properties = {"dummy_model": []}
|
|
modelyamlver.raw = {
|
|
"dummy_service": {
|
|
"methods": [
|
|
{
|
|
"dummy_endpoint1": [{"insignal": "test_insignal"}],
|
|
"dummy_endpoint2": [{"insignal": "test_insignal"}],
|
|
}
|
|
]
|
|
}
|
|
}
|
|
exception_msg = [
|
|
"ERROR:root:You can't connect a signal test_insignal in dummy_model model to two "
|
|
"different primitives. It's already connected in dummy_model model\n"
|
|
]
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.parse_service_definitions(modelyamlver.raw)
|
|
self.assertEqual(warn_info.output, exception_msg)
|
|
|
|
def test_validate_dp_signal_schema(self):
|
|
"""Test the validate_signal_schema method."""
|
|
app = mock.MagicMock()
|
|
modelyamlver = ModelYmlVerification(app)
|
|
modelyamlver.model_name = "dummy_model"
|
|
signal_spec = {"insignal": "test_insignal"}
|
|
exception_msg = "ERROR:root:required key not provided @ data['property'] in dummy_model\n"
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.validate_signal_schema(signal_spec, "insignal", is_hal=False, is_service=False)
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
def test_check_dp_property(self):
|
|
"""Test the verify_primitive method."""
|
|
app = mock.MagicMock()
|
|
modelyamlver = ModelYmlVerification(app)
|
|
modelyamlver.model_name = "dummy_model2"
|
|
modelyamlver.signal_properties = {"dummy_model1": ["dummy_dp.property_outsignal.signal"], "dummy_model2": []}
|
|
exception_msg = (
|
|
"ERROR:root:You can't connect another signal to the existing property "
|
|
"dummy_dp.property_outsignal.signal2"
|
|
" in dummy_model2 model, because it is already defined in dummy_model1 model.\n"
|
|
)
|
|
with self.assertLogs(level="INFO") as warn_info:
|
|
modelyamlver.check_property("dummy_dp.property_outsignal.signal2")
|
|
self.assertEqual(warn_info.output, [exception_msg])
|
|
|
|
app = mock.MagicMock()
|
|
modelyamlver = ModelYmlVerification(app)
|
|
modelyamlver.model_name = "dummy_model2"
|
|
modelyamlver.signal_properties = {"dummy_model1": ["dummy_dp.property_outsignal"], "dummy_model2": []}
|
|
expected_signal_properties = {
|
|
"dummy_model1": ["dummy_dp.property_outsignal"],
|
|
"dummy_model2": ["dummy_dp.property_insignal.signal"],
|
|
}
|
|
modelyamlver.verify_primitive("dummy_dp.property_insignal.signal", "outsignal")
|
|
self.assertEqual(expected_signal_properties, modelyamlver.signal_properties)
|