Files
powertrain-build/tests/zone_controller/test_composition_yaml.py
Henrik Wahlqvist c1e138cb47 Add option for softwareComponentBase
This setting changes the ASIL classification of the software component
by adding the swcbase key to the yaml file.
ZC projects only.

Change-Id: Ic94dbb3cb4ca617f4637066d50ee0817e1e923cc
2024-09-24 16:06:47 +02:00

214 lines
9.4 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_swc_base = MagicMock(return_value="QM")
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"])