summaryrefslogtreecommitdiff
path: root/rtemsspec
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2023-11-21 11:13:16 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2023-11-21 11:15:25 +0100
commit89a0cf739104ffa63eb3db6d39344d539297ac6a (patch)
tree20418aa4db6b0ba2d05f1db28d5c3eb7fc1f8d34 /rtemsspec
parentb0e8c33fe224459a6925cc27b35f0e843dd3fb78 (diff)
rtems: Gather related items
Diffstat (limited to 'rtemsspec')
-rw-r--r--rtemsspec/rtems.py67
-rw-r--r--rtemsspec/tests/test_packagebuild.py24
-rw-r--r--rtemsspec/tests/test_rtems.py5
3 files changed, 85 insertions, 11 deletions
diff --git a/rtemsspec/rtems.py b/rtemsspec/rtems.py
index cd68f036..9bf36b72 100644
--- a/rtemsspec/rtems.py
+++ b/rtemsspec/rtems.py
@@ -27,7 +27,7 @@
import base64
import hashlib
import itertools
-from typing import Any, Dict, List, Tuple, Union
+from typing import Any, Dict, List, Set, Tuple, Union
from rtemsspec.items import create_unique_link, Item, ItemCache, Link
from rtemsspec.glossary import augment_glossary_terms
@@ -161,7 +161,8 @@ _VALIDATOR = {
}
-def _validate_tree(item: Item) -> bool:
+def _validate_tree(item: Item, related_items: Set[Item]) -> bool:
+ related_items.add(item)
pre_qualified = is_pre_qualified(item)
item["_pre_qualified"] = pre_qualified
validated = True
@@ -169,7 +170,7 @@ def _validate_tree(item: Item) -> bool:
for link in itertools.chain(item.links_to_children(_CHILD_ROLES),
item.links_to_parents(_PARENT_ROLES)):
item_2 = link.item
- validated = _validate_tree(item_2) and validated
+ validated = _validate_tree(item_2, related_items) and validated
if link.role == "validation":
role = _VALIDATION_METHOD[item_2.type]
elif link.role == "requirement-refinement":
@@ -229,15 +230,21 @@ def _fixup_pre_qualified(item: Item, types: List[str],
item_2["_pre_qualified"] = False
-def validate(item: Item) -> None:
- """ Validates the item tree starting at the root item. """
- _validate_tree(item)
- _validate_containers(item)
- _fixup_pre_qualified(item,
+def validate(root: Item) -> Set[Item]:
+ """
+ Validates the item tree starting at the root item.
+
+ Returns the set of items related to the root item.
+ """
+ related_items: Set[Item] = set()
+ _validate_tree(root, related_items)
+ _validate_containers(root)
+ _fixup_pre_qualified(root,
["interface/appl-config-group", "interface/group"],
["interface-ingroup", "interface-ingroup-hidden"])
- _fixup_pre_qualified(item, ["interface/header-file"],
+ _fixup_pre_qualified(root, ["interface/header-file"],
"interface-placement")
+ return related_items
_API_INTERFACES = [
@@ -302,7 +309,11 @@ class RTEMSItemCache(BuildItem):
_augment_with_interface_domains(self.item_cache)
for glossary in ["/glossary-general", "/req/glossary"]:
augment_glossary_terms(self.item_cache[glossary], [])
- validate(self.item_cache[self["spec-root-uid"]])
+ self.related_items = validate(self.item_cache[self["spec-root-uid"]])
+ self.related_items_by_type: Dict[str, List[Item]] = {}
+ for item_2 in self.related_items:
+ self.related_items_by_type.setdefault(item_2.type,
+ []).append(item_2)
# Calculate the overall item cache hash. Ignore QDP configuration
# items and specification type changes.
@@ -317,3 +328,39 @@ class RTEMSItemCache(BuildItem):
def refresh_link(self, link: Link) -> None:
link["hash"] = self._hash
+
+ def get_related_items_by_type(self, types: Union[str,
+ List[str]]) -> List[Item]:
+ """ Gets related items by a list of types. """
+ if isinstance(types, str):
+ types = [types]
+ items: List[Item] = []
+ for type_name in types:
+ items.extend(
+ item for item in self.related_items_by_type.get(type_name, []))
+ return sorted(items)
+
+ def get_related_types_by_prefix(
+ self, prefix: Union[str, Tuple[str, ...]]) -> List[str]:
+ """
+ Gets the types of the related items having one of the type prefixes.
+ """
+ return [
+ type_name for type_name in sorted(self.related_items_by_type)
+ if type_name.startswith(prefix)
+ ]
+
+ def get_related_interfaces(self) -> List[Item]:
+ """ Gets the related interfaces. """
+ return self.get_related_items_by_type(
+ self.get_related_types_by_prefix("interface/"))
+
+ def get_related_requirements(self) -> List[Item]:
+ """ Gets the related requirements. """
+ return self.get_related_items_by_type(
+ self.get_related_types_by_prefix("requirement/"))
+
+ def get_related_interfaces_and_requirements(self) -> List[Item]:
+ """ Gets the related interfaces and requirements. """
+ return self.get_related_items_by_type(
+ self.get_related_types_by_prefix(("interface/", "requirement/")))
diff --git a/rtemsspec/tests/test_packagebuild.py b/rtemsspec/tests/test_packagebuild.py
index fa0309d9..6ff9c8e4 100644
--- a/rtemsspec/tests/test_packagebuild.py
+++ b/rtemsspec/tests/test_packagebuild.py
@@ -38,6 +38,7 @@ from rtemsspec.items import EmptyItem, Item, ItemCache, ItemGetValueContext
from rtemsspec.packagebuild import BuildItem, BuildItemMapper, \
build_item_input, PackageBuildDirector
from rtemsspec.packagebuildfactory import create_build_item_factory
+from rtemsspec.rtems import RTEMSItemCache
from rtemsspec.specverify import verify
import rtemsspec.testrunner
from rtemsspec.testrunner import Executable, Report, TestRunner
@@ -144,6 +145,29 @@ def test_packagebuild(caplog, tmpdir, monkeypatch):
assert "INFO /qdp/steps/b: is disabled" in log
assert "INFO /qdp/steps/c: output is disabled: /qdp/output/b" in log
+ rtems_item_cache = director["/qdp/steps/rtems-item-cache"]
+ assert isinstance(rtems_item_cache, RTEMSItemCache)
+ related_items = rtems_item_cache.get_related_items_by_type("test-case")
+ assert [item.uid for item in related_items] == ["/rtems/test-case"]
+ related_items = rtems_item_cache.get_related_items_by_type(["test-case"])
+ assert [item.uid for item in related_items] == ["/rtems/test-case"]
+ related_types = rtems_item_cache.get_related_types_by_prefix("requirement")
+ assert related_types == [
+ "requirement/functional/function", "requirement/non-functional/design"
+ ]
+ related_items = rtems_item_cache.get_related_interfaces()
+ assert [item.uid for item in related_items] == [
+ "/rtems/domain", "/rtems/group", "/rtems/group-acfg", "/rtems/header",
+ "/rtems/if"
+ ]
+ related_items = rtems_item_cache.get_related_requirements()
+ assert [item.uid for item in related_items] == ["/req/root", "/rtems/req"]
+ related_items = rtems_item_cache.get_related_interfaces_and_requirements()
+ assert [item.uid for item in related_items] == [
+ "/req/root", "/rtems/domain", "/rtems/group", "/rtems/group-acfg",
+ "/rtems/header", "/rtems/if", "/rtems/req"
+ ]
+
director.build_package(None, ["/qdp/steps/a"])
log = get_and_clear_log(caplog)
assert "INFO /qdp/steps/a: build is forced" in log
diff --git a/rtemsspec/tests/test_rtems.py b/rtemsspec/tests/test_rtems.py
index ae399f8a..28586612 100644
--- a/rtemsspec/tests/test_rtems.py
+++ b/rtemsspec/tests/test_rtems.py
@@ -124,7 +124,10 @@ def test_validate(tmpdir):
item_cache_config = create_item_cache_config_and_copy_spec(
tmpdir, "spec-rtems", with_spec_types=True)
item_cache = ItemCache(item_cache_config)
- assert not validate(item_cache["/req/root"])
+ root = item_cache["/req/root"]
+ assert "_validated" not in root
+ validate(root)
+ assert not root["_validated"]
api_items = {}
gather_api_items(item_cache, api_items)
assert [