powertrain-build/tests/zone_controller/test_composition_yaml.py
Henrik Wahlqvist fda739bc13 Refactor usage of ecu_supplier
Removed most of the decisions based on ecu_supplier and made it more
granular using individual configuration.
Current project types will keep their config by adding templates in the
BaseConfig.json file.
Some usecases were kept for legacy reasons.

Change-Id: I3d6199713006489baff0bf73751596770fd1f968
2024-09-17 08:25:46 +00:00

213 lines
9.3 KiB
Python

# Copyright 2024 Volvo Car Corporation
# Licensed under Apache 2.0.
"""Unit test script for powertrain_build.zone_controller.generate_yaml."""
import copy
import os
import unittest
from pathlib import Path
from unittest.mock import MagicMock, patch
from powertrain_build.build_proj_config import BuildProjConfig
from powertrain_build.core import ZCCore
from powertrain_build.dids import ZCDIDs
from powertrain_build.unit_configs import UnitConfigs
from powertrain_build.zone_controller.composition_yaml import CompositionYaml
from test_data.zone_controller.test_composition_yaml import (
composition_yaml_setup,
composition_yaml,
composition_yaml_with_a2l_axis_data,
composition_yaml_with_calls_all_fields,
composition_yaml_with_calls_no_optional_fields,
composition_yaml_with_dids,
composition_yaml_with_dtcs,
)
SRC_DIR = Path(__file__).parent
class BuildProjConfigMock(BuildProjConfig):
"""Class mocking BuildProjConfig"""
name = ""
class TestCompositionYaml(unittest.TestCase):
"""Test case for testing composition_yaml."""
def setUp(self):
"""Set-up common data structures for all tests in the test case."""
self.build_cfg = MagicMock(spec_set=BuildProjConfigMock)
self.build_cfg.name = "XVC"
self.build_cfg.get_scheduler_prefix = MagicMock(return_value="prefix_")
self.build_cfg.get_src_code_dst_dir = MagicMock(
return_value=os.path.abspath("output")
)
self.build_cfg.get_composition_arxml = MagicMock(return_value="some_arxml.arxml")
self.build_cfg.get_units_raster_cfg = MagicMock(
return_value=({"SampleTimes": {"testRunnable": 10}})
)
self.build_cfg.get_composition_name = MagicMock(return_value="compositionName")
self.build_cfg.get_swc_name = MagicMock(return_value="testName_SC")
self.build_cfg.get_swc_template = MagicMock(return_value="ARTCSC")
self.build_cfg.get_gen_ext_impl_type = MagicMock(return_value=True)
self.build_cfg.get_code_generation_config = MagicMock(return_value=False)
self.unit_cfg = MagicMock(spec_set=UnitConfigs)
self.unit_cfg.get_per_cfg_unit_cfg.return_value = copy.deepcopy(
composition_yaml_setup.get_per_cfg_unit_cfg_return_value
)
with patch.object(ZCCore, "_get_project_dtcs", return_value=set()):
self.zc_core = ZCCore(self.build_cfg, self.unit_cfg)
with patch.object(ZCDIDs, "_get_project_dids", return_value={}):
self.zc_dids = ZCDIDs(self.build_cfg, self.unit_cfg)
self.zc_spec = copy.deepcopy(composition_yaml_setup.zc_spec)
self.calibration_definitions = copy.deepcopy(composition_yaml_setup.calibration_definitions)
with patch.object(
CompositionYaml,
"_get_all_calibration_definitions",
return_value=self.calibration_definitions
):
self.composition_yaml = CompositionYaml(
self.build_cfg, self.zc_spec, self.unit_cfg, self.zc_core, self.zc_dids, {}
)
def test_check_unsupported_fields(self):
"""Test CompositionYaml.check_unsupported_fields."""
self.composition_yaml.warning = MagicMock()
test_data = {
"name": "sVcGpaDemo_D_BrkCtrlr",
"type": "UInt8",
"class": "CVC_DISP",
"lsb": 1,
"offset": "-",
"width": 1,
}
self.composition_yaml.check_unsupported_fields("dummy", test_data)
self.composition_yaml.warning.assert_not_called()
test_data["lsb"] = 10
self.composition_yaml.check_unsupported_fields("dummy", test_data)
self.composition_yaml.warning.assert_called_once()
def test_composition_yaml(self):
"""Checking that the dict is generated correctly"""
result = self.composition_yaml.gather_yaml_info()
self.assertDictEqual(composition_yaml.expected_result, result)
def test_composition_yaml_with_calibration(self):
"""Checking that the dict is generated correctly including calibration data,
setting generateCalibrationInterfaceFiles to true (sort of)."""
self.build_cfg.get_code_generation_config = MagicMock(return_value=True)
with patch.object(
CompositionYaml,
"_get_all_calibration_definitions",
return_value=self.calibration_definitions
):
self.composition_yaml = CompositionYaml(
self.build_cfg, self.zc_spec, self.unit_cfg, self.zc_core, self.zc_dids, {}
)
result = self.composition_yaml.gather_yaml_info()
self.assertDictEqual(composition_yaml.expected_cal_result, result)
def test_composition_yaml_with_a2l_axis_data(self):
"""Checking that the dict is generated correctly, including a2l axis data."""
self.unit_cfg.get_per_cfg_unit_cfg.return_value = \
composition_yaml_with_a2l_axis_data.get_per_cfg_unit_cfg_return_value
a2l_axis_data = composition_yaml_with_a2l_axis_data.a2l_axis_data
calibration_definitions = \
self.calibration_definitions + composition_yaml_with_a2l_axis_data.calibration_definitions
with patch.object(CompositionYaml, "_get_all_calibration_definitions", return_value=calibration_definitions):
self.composition_yaml = CompositionYaml(
self.build_cfg, self.zc_spec, self.unit_cfg, self.zc_core, self.zc_dids, a2l_axis_data
)
result = self.composition_yaml.gather_yaml_info()
self.assertDictEqual(composition_yaml_with_a2l_axis_data.expected_result, result)
def test_composition_yaml_with_calls_all_fields(self):
"""Checking that the dict is generated correctly, with calls including all fields."""
self.zc_spec["calls"] = {
"CallOne": {
"interface": "InterfaceOne",
"direction": "IN",
"operation": "OperationOne",
"timeout": 0.1,
}
}
with patch.object(
CompositionYaml,
"_get_all_calibration_definitions",
return_value=self.calibration_definitions
):
self.composition_yaml = CompositionYaml(
self.build_cfg, self.zc_spec, self.unit_cfg, self.zc_core, self.zc_dids, {}
)
result = self.composition_yaml.gather_yaml_info()
self.assertDictEqual(composition_yaml_with_calls_all_fields.expected_result, result)
def test_composition_yaml_with_calls_no_optional_fields(self):
"""Checking that the dict is generated correctly, with calls without optional fields."""
self.zc_spec["calls"] = {
"CallOne": {
"direction": "IN",
"operation": "OperationOne",
}
}
with patch.object(
CompositionYaml,
"_get_all_calibration_definitions",
return_value=self.calibration_definitions
):
self.composition_yaml = CompositionYaml(
self.build_cfg, self.zc_spec, self.unit_cfg, self.zc_core, self.zc_dids, {}
)
result = self.composition_yaml.gather_yaml_info()
self.assertDictEqual(composition_yaml_with_calls_no_optional_fields.expected_result, result)
def test_composition_yaml_with_dids(self):
"""Checking that the dict is generated correctly, with DIDs."""
self.zc_dids.project_dids = {"DID1": {"type": "UInt8"}}
self.zc_spec["Diagnostics"] = composition_yaml_with_dids.diagnostics
with patch.object(
CompositionYaml,
"_get_all_calibration_definitions",
return_value=self.calibration_definitions
):
self.composition_yaml = CompositionYaml(
self.build_cfg, self.zc_spec, self.unit_cfg, self.zc_core, self.zc_dids, {}
)
result = self.composition_yaml.gather_yaml_info()
self.assertDictEqual(composition_yaml_with_dids.expected_result, result)
def test_composition_yaml_with_dtcs(self):
"""Checking that the dict is generated correctly, with DTCs."""
self.zc_core.project_dtcs = {"DTC1"}
self.zc_spec["Diagnostics"] = composition_yaml_with_dtcs.diagnostics
with patch.object(
CompositionYaml,
"_get_all_calibration_definitions",
return_value=self.calibration_definitions
):
self.composition_yaml = CompositionYaml(
self.build_cfg, self.zc_spec, self.unit_cfg, self.zc_core, self.zc_dids, {}
)
result = self.composition_yaml.gather_yaml_info()
self.assertDictEqual(composition_yaml_with_dtcs.expected_result, result)
def test_get_init_values_expecting_failure(self):
"""Test CompositionYaml.get_init_values with a non-existing calibration definition."""
self.composition_yaml.clear_log()
json_variables = {"signal_name": "dummy"}
c_definitions = ["CVC_CAL Float32 signal_name_other = 1.F; "]
with patch.object(CompositionYaml, "_get_all_calibration_definitions", return_value=c_definitions):
init_values = self.composition_yaml.get_init_values(json_variables)
logged_problems = self.composition_yaml.get_problems()
self.assertEqual(init_values, {})
self.assertEqual(logged_problems["warning"], [])
self.assertEqual(logged_problems["critical"], ["Missing init values for calibration variables:\nsignal_name"])