[rtems-central commit] specview.py: Share validation support

Sebastian Huber sebh at rtems.org
Tue Nov 21 13:35:40 UTC 2023


Module:    rtems-central
Branch:    master
Commit:    47da37564e25c1f88dfe832eecc5ec57c6784ada
Changeset: http://git.rtems.org/rtems-central/commit/?id=47da37564e25c1f88dfe832eecc5ec57c6784ada

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Tue Nov 21 11:13:15 2023 +0100

specview.py: Share validation support

---

 rtemsspec/rtems.py                                 | 140 ++++++++++++++++++++-
 rtemsspec/tests/spec-rtems/constraint/bad.yml      |  11 ++
 .../constraint/constant-not-pre-qualified.yml      |  13 ++
 .../tests/spec-rtems/constraint/terminate.yml      |  11 ++
 rtemsspec/tests/spec-rtems/glossary-general.yml    |  12 ++
 rtemsspec/tests/spec-rtems/glossary/api.yml        |  12 ++
 rtemsspec/tests/spec-rtems/glossary/bad.yml        |  12 ++
 .../spec-rtems/if/disable-newlib-reentrancy.yml    |  22 ++++
 rtemsspec/tests/spec-rtems/if/domain.yml           |  13 ++
 rtemsspec/tests/spec-rtems/if/errno-header.yml     |  15 +++
 rtemsspec/tests/spec-rtems/if/errno.yml            |  14 +++
 rtemsspec/tests/spec-rtems/if/group-general.yml    |  16 +++
 rtemsspec/tests/spec-rtems/if/group.yml            |  17 +++
 rtemsspec/tests/spec-rtems/if/header-confdefs.yml  |  16 +++
 .../spec-rtems/if/not-pre-qualified-header.yml     |  15 +++
 .../tests/spec-rtems/if/not-pre-qualified.yml      |  16 +++
 .../spec-rtems/req/disable-newlib-reentrancy.yml   |  17 +++
 rtemsspec/tests/spec-rtems/req/group.yml           |  16 +++
 rtemsspec/tests/spec-rtems/req/perf-limits.yml     |  36 ++++++
 rtemsspec/tests/spec-rtems/req/perf-runtime.yml    |  59 +++++++++
 rtemsspec/tests/spec-rtems/req/root.yml            |  12 ++
 .../tests/spec-rtems/req/usage-constraints.yml     |  14 +++
 .../spec-rtems/val/disable-newlib-reentrancy.yml   |  25 ++++
 rtemsspec/tests/spec-rtems/val/perf.yml            |  58 +++++++++
 rtemsspec/tests/spec/functional-more.yml           |   4 +
 rtemsspec/tests/spec/non-functional-more.yml       |   8 ++
 rtemsspec/tests/spec/validation-more.yml           |  21 ++++
 rtemsspec/tests/spec/validation.yml                |  24 ++++
 rtemsspec/tests/test_rtems.py                      |  14 ++-
 specview.py                                        |  76 +----------
 30 files changed, 664 insertions(+), 75 deletions(-)

diff --git a/rtemsspec/rtems.py b/rtemsspec/rtems.py
index 94b2d1fb..6407de19 100644
--- a/rtemsspec/rtems.py
+++ b/rtemsspec/rtems.py
@@ -24,7 +24,8 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-from typing import Any, List
+import itertools
+from typing import Any, List, Tuple, Union
 
 from rtemsspec.items import create_unique_link, Item, ItemCache, Link
 
@@ -82,3 +83,140 @@ def augment_with_test_links(item_cache: ItemCache) -> None:
                     _add_link(item_cache, item, link)
             for link in actions["links"]:
                 _add_link(item_cache, item, link)
+
+
+_SELF_VALIDATION = {
+    "memory-benchmark": "memory benchmark",
+    "requirement/functional/action": "validation by test",
+    "requirement/non-functional/performance-runtime": "validation by test",
+    "runtime-measurement-test": "validation by test"
+}
+
+_VALIDATION_METHOD = {
+    "memory-benchmark": "validation by inspection",
+    "requirement/functional/action": "validation by test",
+    "requirement/non-functional/performance-runtime": "validation by test",
+    "runtime-measurement-test": "validation by test",
+    "test-case": "validation by test",
+    "validation/by-analysis": "validation by analysis",
+    "validation/by-inspection": "validation by inspection",
+    "validation/by-review-of-design": "validation by review of design",
+}
+
+_CONTAINER_TYPE = ["interface/domain", "interface/header-file"]
+
+# In the first pass using _validate_tree() we consider interface domains and
+# header files as validated.  We have to do this since a traversal to interface
+# placements would lead to an infinite recursion in _validate_tree().  In the
+# second pass using _validate_containers() the interface domain and header file
+# validations are fixed.
+_VALIDATION_LEAF = list(_VALIDATION_METHOD.keys()) + _CONTAINER_TYPE
+
+_CHILD_ROLES = [
+    "requirement-refinement", "interface-ingroup", "interface-ingroup-hidden",
+    "interface-function", "glossary-member", "test-case", "validation"
+]
+
+_PARENT_ROLES = [
+    "function-implementation", "interface-enumerator",
+    "performance-runtime-limits"
+]
+
+
+def _validate_glossary_term(item: Item) -> bool:
+    for item_2 in item.parents("glossary-member"):
+        if item_2.type != "glossary/group":
+            return False
+    return True
+
+
+def _validate_constraint(item: Item) -> bool:
+    for item_2 in item.parents("requirement-refinement"):
+        if item_2.uid != "/req/usage-constraints":
+            return False
+    return True
+
+
+_VALIDATOR = {
+    "constraint": _validate_constraint,
+    "glossary/term": _validate_glossary_term
+}
+
+
+def _validate_tree(item: Item) -> bool:
+    pre_qualified = is_pre_qualified(item)
+    item["_pre_qualified"] = pre_qualified
+    validated = True
+    validation_dependencies: List[Tuple[str, str]] = []
+    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
+        if link.role == "validation":
+            role = _VALIDATION_METHOD[item_2.type]
+        elif link.role == "requirement-refinement":
+            role = "refinement"
+        elif link.role.startswith("interface-ingroup"):
+            role = "group member"
+        elif link.role == "performance-runtime-limits":
+            role = "runtime performance requirement"
+        else:
+            role = link.role.replace("-", " ")
+        validation_dependencies.append((item_2.uid, role))
+    type_name = item.type
+    if type_name in _SELF_VALIDATION:
+        validation_dependencies.append((item.uid, _SELF_VALIDATION[type_name]))
+    elif not validation_dependencies:
+        if type_name in _VALIDATOR:
+            validated = _VALIDATOR[type_name](item)
+        else:
+            validated = (not pre_qualified) or (type_name in _VALIDATION_LEAF)
+    if type_name in _CONTAINER_TYPE:
+        validation_dependencies.extend(
+            (item_2.uid, "interface placement")
+            for item_2 in item.children("interface-placement"))
+    item["_validated"] = validated
+    item["_validation_dependencies"] = sorted(validation_dependencies)
+    return validated
+
+
+def _validate_containers(item: Item) -> bool:
+    validated = item["_validated"]
+    if item.type in _CONTAINER_TYPE:
+        # If at least one not validated child exists, then the container is not
+        # validated
+        for item_2 in item.children("interface-placement"):
+            if not item_2["_validated"]:
+                validated = False
+                item["_validated"] = validated
+                break
+    for item_2 in itertools.chain(item.children(_CHILD_ROLES),
+                                  item.parents(_PARENT_ROLES)):
+        validated = _validate_containers(item_2) and validated
+    return validated
+
+
+def _fixup_pre_qualified(item: Item, types: List[str],
+                         roles: Union[str, List[str]]) -> None:
+    for type_name in types:
+        for item_2 in item.cache.items_by_type[type_name]:
+            # Count of not pre-qualified (index 0) and pre-qualified (index 1)
+            # children
+            count = [0, 0]
+            for item_3 in item_2.children(roles):
+                count[int(item_3["_pre_qualified"])] += 1
+            # If at least one not pre-qualified child exists and no
+            # pre-qualified child exists, then the item is not pre-qualified.
+            if count[0] > 0 and count[1] == 0:
+                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,
+                         ["interface/appl-config-group", "interface/group"],
+                         ["interface-ingroup", "interface-ingroup-hidden"])
+    _fixup_pre_qualified(item, ["interface/header-file"],
+                         "interface-placement")
diff --git a/rtemsspec/tests/spec-rtems/constraint/bad.yml b/rtemsspec/tests/spec-rtems/constraint/bad.yml
new file mode 100644
index 00000000..89210c43
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/constraint/bad.yml
@@ -0,0 +1,11 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: ../req/usage-constraints
+rationale: null
+text: |
+  The directive may terminate the system.
+type: constraint
diff --git a/rtemsspec/tests/spec-rtems/constraint/constant-not-pre-qualified.yml b/rtemsspec/tests/spec-rtems/constraint/constant-not-pre-qualified.yml
new file mode 100644
index 00000000..20ae5248
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/constraint/constant-not-pre-qualified.yml
@@ -0,0 +1,13 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: ../req/usage-constraints
+rationale: null
+text: |
+  The constant is not included in the pre-qualified feature set of RTEMS.
+  Applications which are restricted to only use interfaces of the pre-qualified
+  feature set of RTEMS shall not use the constant.
+type: constraint
diff --git a/rtemsspec/tests/spec-rtems/constraint/terminate.yml b/rtemsspec/tests/spec-rtems/constraint/terminate.yml
new file mode 100644
index 00000000..4250bb03
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/constraint/terminate.yml
@@ -0,0 +1,11 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: ../req/root
+rationale: null
+text: |
+  The directive may terminate the system.
+type: constraint
diff --git a/rtemsspec/tests/spec-rtems/glossary-general.yml b/rtemsspec/tests/spec-rtems/glossary-general.yml
new file mode 100644
index 00000000..b5118577
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/glossary-general.yml
@@ -0,0 +1,12 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH & Co. KG
+enabled-by: true
+glossary-type: group
+links:
+- role: requirement-refinement
+  uid: req/root
+name: General
+text: |
+  The system shall have a general glossary of terms.
+type: glossary
diff --git a/rtemsspec/tests/spec-rtems/glossary/api.yml b/rtemsspec/tests/spec-rtems/glossary/api.yml
new file mode 100644
index 00000000..98a0ab73
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/glossary/api.yml
@@ -0,0 +1,12 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2017 embedded brains GmbH & Co. KG
+enabled-by: true
+glossary-type: term
+links:
+- role: glossary-member
+  uid: ../glossary-general
+term: API
+text: |
+  This term is an acronym for Application Programming Interface.
+type: glossary
diff --git a/rtemsspec/tests/spec-rtems/glossary/bad.yml b/rtemsspec/tests/spec-rtems/glossary/bad.yml
new file mode 100644
index 00000000..4ef1a692
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/glossary/bad.yml
@@ -0,0 +1,12 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2017 embedded brains GmbH & Co. KG
+enabled-by: true
+glossary-type: term
+links:
+- role: glossary-member
+  uid: ../req/root
+term: API
+text: |
+  This term is an acronym for Application Programming Interface.
+type: glossary
diff --git a/rtemsspec/tests/spec-rtems/if/disable-newlib-reentrancy.yml b/rtemsspec/tests/spec-rtems/if/disable-newlib-reentrancy.yml
new file mode 100644
index 00000000..a18e9678
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/if/disable-newlib-reentrancy.yml
@@ -0,0 +1,22 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+appl-config-option-type: feature-enable
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH & Co. KG
+description: |
+  In case this configuration option is defined, then the Newlib reentrancy
+  support per thread is disabled and a global reentrancy structure is used.
+enabled-by: true
+index-entries: []
+interface-type: appl-config-option
+links:
+- role: interface-placement
+  uid: domain
+- role: interface-ingroup
+  uid: group-general
+name: CONFIGURE_DISABLE_NEWLIB_REENTRANCY
+notes: |
+  You can enable this option to reduce the size of the :term:`TCB`.  Use this
+  option with care, since it can lead to race conditions and undefined system
+  behaviour.  For example, errno is no longer a thread-local
+  variable if this option is enabled.
+type: interface
diff --git a/rtemsspec/tests/spec-rtems/if/domain.yml b/rtemsspec/tests/spec-rtems/if/domain.yml
new file mode 100644
index 00000000..9d499db1
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/if/domain.yml
@@ -0,0 +1,13 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+description: |
+  This interface domain contains the application configuration.
+enabled-by: true
+index-entries: []
+interface-type: domain
+links:
+- role: requirement-refinement
+  uid: ../req/root
+name: Application Configuration
+type: interface
diff --git a/rtemsspec/tests/spec-rtems/if/errno-header.yml b/rtemsspec/tests/spec-rtems/if/errno-header.yml
new file mode 100644
index 00000000..5018bf09
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/if/errno-header.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+brief: This is a standard C library header file.
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH & Co. KG
+enabled-by: true
+index-entries: []
+interface-type: header-file
+links:
+- role: interface-placement
+  uid: domain
+- role: interface-ingroup
+  uid: group
+path: errno.h
+prefix: ''
+type: interface
diff --git a/rtemsspec/tests/spec-rtems/if/errno.yml b/rtemsspec/tests/spec-rtems/if/errno.yml
new file mode 100644
index 00000000..09e55795
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/if/errno.yml
@@ -0,0 +1,14 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH & Co. KG
+enabled-by: true
+index-entries: []
+interface-type: unspecified-define
+links:
+- role: interface-placement
+  uid: errno-header
+- role: interface-ingroup
+  uid: group
+name: errno
+references: []
+type: interface
diff --git a/rtemsspec/tests/spec-rtems/if/group-general.yml b/rtemsspec/tests/spec-rtems/if/group-general.yml
new file mode 100644
index 00000000..0e9bb163
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/if/group-general.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 1988, 2008 On-Line Applications Research Corporation (OAR)
+description: |
+  This section describes general system configuration options.
+enabled-by: true
+index-entries: []
+interface-type: appl-config-group
+links:
+- role: interface-placement
+  uid: domain
+- role: requirement-refinement
+  uid: ../req/root
+name: General System Configuration
+text: ''
+type: interface
diff --git a/rtemsspec/tests/spec-rtems/if/group.yml b/rtemsspec/tests/spec-rtems/if/group.yml
new file mode 100644
index 00000000..1f43773c
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/if/group.yml
@@ -0,0 +1,17 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+identifier: RTEMSApplConfig
+index-entries: []
+interface-type: group
+links:
+- role: requirement-refinement
+  uid: ../req/root
+- role: interface-placement
+  uid: domain
+name: Application Configuration
+text: |
+  The API shall contain the application configuration
+  interface.
+type: interface
diff --git a/rtemsspec/tests/spec-rtems/if/header-confdefs.yml b/rtemsspec/tests/spec-rtems/if/header-confdefs.yml
new file mode 100644
index 00000000..680c7c17
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/if/header-confdefs.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+brief: |
+  This header file initializes the application configuration.
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+index-entries: []
+interface-type: header-file
+links:
+- role: interface-placement
+  uid: domain
+- role: interface-ingroup
+  uid: group
+path: rtems/confdefs.h
+prefix: cpukit/include
+type: interface
diff --git a/rtemsspec/tests/spec-rtems/if/not-pre-qualified-header.yml b/rtemsspec/tests/spec-rtems/if/not-pre-qualified-header.yml
new file mode 100644
index 00000000..4fc27470
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/if/not-pre-qualified-header.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+brief: Not pre-qualified header.
+copyrights:
+- Copyright (C) 2023 embedded brains GmbH & Co. KG
+enabled-by: true
+index-entries: []
+interface-type: header-file
+links:
+- role: interface-placement
+  uid: domain
+- role: interface-ingroup
+  uid: group
+path: not-pre-qualified.h
+prefix: ''
+type: interface
diff --git a/rtemsspec/tests/spec-rtems/if/not-pre-qualified.yml b/rtemsspec/tests/spec-rtems/if/not-pre-qualified.yml
new file mode 100644
index 00000000..d3ccfbcc
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/if/not-pre-qualified.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2023 embedded brains GmbH & Co. KG
+enabled-by: true
+index-entries: []
+interface-type: unspecified-define
+links:
+- role: interface-placement
+  uid: not-pre-qualified-header
+- role: interface-ingroup
+  uid: group
+- role: constraint
+  uid: ../constraint/constant-not-pre-qualified
+name: NOT_PRE_QUALIFIED
+references: []
+type: interface
diff --git a/rtemsspec/tests/spec-rtems/req/disable-newlib-reentrancy.yml b/rtemsspec/tests/spec-rtems/req/disable-newlib-reentrancy.yml
new file mode 100644
index 00000000..6a881a08
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/req/disable-newlib-reentrancy.yml
@@ -0,0 +1,17 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+functional-type: function
+links:
+- role: interface-function
+  uid: ../if/disable-newlib-reentrancy
+- role: requirement-refinement
+  uid: group
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  The application configuration option shall disable the thread-specific Newlib
+  reentrancy support.
+type: requirement
diff --git a/rtemsspec/tests/spec-rtems/req/group.yml b/rtemsspec/tests/spec-rtems/req/group.yml
new file mode 100644
index 00000000..e9df0e95
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/req/group.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+identifier: RTEMSImplApplConfig
+links:
+- role: requirement-refinement
+  uid: root
+non-functional-type: design-group
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The implementation software architecture component have a component
+  containing the application configuration implementation.
+type: requirement
diff --git a/rtemsspec/tests/spec-rtems/req/perf-limits.yml b/rtemsspec/tests/spec-rtems/req/perf-limits.yml
new file mode 100644
index 00000000..ecad9d40
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/req/perf-limits.yml
@@ -0,0 +1,36 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2023 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: root
+- limits:
+    DirtyCache:
+      max-upper-bound: 6.36e-06
+      median-lower-bound: 1.57e-06
+      median-upper-bound: 6.28e-06
+      min-lower-bound: 1.57e-06
+    FullCache:
+      max-upper-bound: 5.96e-06
+      median-lower-bound: 1.48e-06
+      median-upper-bound: 5.92e-06
+      min-lower-bound: 1.48e-06
+    HotCache:
+      max-upper-bound: 5.88e-06
+      median-lower-bound: 1.47e-06
+      median-upper-bound: 5.88e-06
+      min-lower-bound: 1.47e-06
+    Load/1:
+      max-upper-bound: 1.596e-05
+      median-lower-bound: 3.99e-06
+      median-upper-bound: 1.596e-05
+      min-lower-bound: 3.98e-06
+  role: performance-runtime-limits
+  uid: perf-runtime
+non-functional-type: performance-runtime-limits
+rationale: null
+references: []
+requirement-type: non-functional
+text: ${.:text-template}
+type: requirement
diff --git a/rtemsspec/tests/spec-rtems/req/perf-runtime.yml b/rtemsspec/tests/spec-rtems/req/perf-runtime.yml
new file mode 100644
index 00000000..cae4ec31
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/req/perf-runtime.yml
@@ -0,0 +1,59 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: root
+- role: runtime-measurement-request
+  uid: ../val/perf
+non-functional-type: performance-runtime
+params: {}
+rationale: null
+references: []
+requirement-type: non-functional
+test-body:
+  brief: |
+    Automatically release the barrier.
+  code: |
+    ctx->status = rtems_barrier_wait( ctx->barrier_id, RTEMS_NO_TIMEOUT );
+  description: null
+test-cleanup:
+  brief: |
+    Delete the barrier and the worker.
+  code: |
+    rtems_status_code sc;
+
+    sc = rtems_barrier_delete( ctx->barrier_id );
+    T_rsc_success( sc );
+  description: null
+test-prepare:
+  brief: |
+    Create an automatic release barrier.
+  code: |
+    rtems_status_code sc;
+
+    sc = rtems_barrier_create(
+      OBJECT_NAME,
+      RTEMS_BARRIER_AUTOMATIC_RELEASE,
+      1,
+      &ctx->barrier_id
+    );
+    T_rsc_success( sc );
+  description: null
+test-setup: null
+test-teardown:
+  brief: |
+    Discard samples interrupted by a clock tick.
+  code: |
+    T_quiet_rsc_success( ctx->status );
+
+    return tic == toc;
+  description: null
+text: |
+  While the execution environment is ${.:/environment}, while the barrier is an
+  automatic release barrier, while the measurement sample is the runtime of
+  exactly one successful call to ${../if/wait:/name} which automatically
+  releases the barrier, when exactly ${../val/perf:/params/sample-count}
+  samples are collected, the ${.:/limit-kind} shall be ${.:/limit-condition}.
+type: requirement
diff --git a/rtemsspec/tests/spec-rtems/req/root.yml b/rtemsspec/tests/spec-rtems/req/root.yml
new file mode 100644
index 00000000..0cb3ba69
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/req/root.yml
@@ -0,0 +1,12 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH & Co. KG
+enabled-by: true
+links: []
+non-functional-type: design
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The software product shall be a real-time operating system.
+type: requirement
diff --git a/rtemsspec/tests/spec-rtems/req/usage-constraints.yml b/rtemsspec/tests/spec-rtems/req/usage-constraints.yml
new file mode 100644
index 00000000..75c42c2d
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/req/usage-constraints.yml
@@ -0,0 +1,14 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: root
+non-functional-type: design
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The system shall document usage constraints of interfaces.
+type: requirement
diff --git a/rtemsspec/tests/spec-rtems/val/disable-newlib-reentrancy.yml b/rtemsspec/tests/spec-rtems/val/disable-newlib-reentrancy.yml
new file mode 100644
index 00000000..ff29201d
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/val/disable-newlib-reentrancy.yml
@@ -0,0 +1,25 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2022 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: validation
+  uid: ../req/disable-newlib-reentrancy
+method: by-inspection
+references: []
+text: |
+  Defining ${../if/disable-newlib-reentrancy:/name} is mandatory for
+  applications using only the pre-qualified feature set.  The reason is to get
+  linker errors in case such applications are linked if they depend on the
+  Newlib reentrancy support.  Thus no validation test case can be used.
+  Inspection of the referenced ${/glossary/sourcecode:/term} files showed that
+  an initial extension set is registered, if
+  ${../if/disable-newlib-reentrancy:/name} is not defined.  For the
+  pre-qualified only build of RTEMS, this would lead to an unresolved reference
+  linker error.  If ${../if/disable-newlib-reentrancy:/name} is defined, then
+  the ``__getreent()`` function is not provided by RTEMS.  If
+  ${../if/disable-newlib-reentrancy:/name} is defined, then the Newlib
+  reentrancy structure is not contained in the ${/glossary/tcb:/term}.  This
+  shows that the ${../req/disable-newlib-reentrancy:/spec} requirement is implemented
+  as specified.
+type: validation
diff --git a/rtemsspec/tests/spec-rtems/val/perf.yml b/rtemsspec/tests/spec-rtems/val/perf.yml
new file mode 100644
index 00000000..0fa5649e
--- /dev/null
+++ b/rtemsspec/tests/spec-rtems/val/perf.yml
@@ -0,0 +1,58 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: validation
+  uid: ../req/root
+params:
+  sample-count: 100
+test-brief: |
+  This test case provides a context to run ${../if/group:/name} performance
+  tests.
+test-cleanup: null
+test-context:
+- brief: |
+    This member provides a barrier identifier.
+  description: null
+  member: |
+    rtems_id barrier_id
+- brief: |
+    This member provides a worker identifier.
+  description: null
+  member: |
+    rtems_id worker_id
+- brief: |
+    This member provides a status code.
+  description: null
+  member: |
+    rtems_status_code status
+test-context-support: null
+test-description: null
+test-includes:
+- rtems.h
+test-local-includes:
+- tx-support.h
+test-prepare: null
+test-setup: null
+test-stop: null
+test-support: |
+  typedef ${.:/test-context-type} Context;
+
+  static void BarrierWaitWorker( rtems_task_argument arg )
+  {
+    Context *ctx;
+
+    ctx = (Context *) arg;
+
+    while ( true ) {
+      rtems_status_code sc;
+
+      sc = rtems_barrier_wait( ctx->barrier_id, RTEMS_NO_TIMEOUT );
+      ctx->end = T_tick();
+      T_quiet_rsc_success( sc );
+    }
+  }
+test-target: testsuites/validation/tc-barrier-performance.c
+test-teardown: null
+type: runtime-measurement-test
diff --git a/rtemsspec/tests/spec/functional-more.yml b/rtemsspec/tests/spec/functional-more.yml
index a7dffe19..3a1b65af 100644
--- a/rtemsspec/tests/spec/functional-more.yml
+++ b/rtemsspec/tests/spec/functional-more.yml
@@ -9,6 +9,10 @@ links:
   spec-key: functional-type
   spec-value: action
   uid: functional
+- role: spec-refinement
+  spec-key: functional-type
+  spec-value: function
+  uid: functional
 spec-description: null
 spec-example: null
 spec-info:
diff --git a/rtemsspec/tests/spec/non-functional-more.yml b/rtemsspec/tests/spec/non-functional-more.yml
index b7535e0c..aa64a2b2 100644
--- a/rtemsspec/tests/spec/non-functional-more.yml
+++ b/rtemsspec/tests/spec/non-functional-more.yml
@@ -5,6 +5,10 @@ enabled-by: true
 links:
 - role: spec-member
   uid: root
+- role: spec-refinement
+  spec-key: non-functional-type
+  spec-value: design
+  uid: non-functional
 - role: spec-refinement
   spec-key: non-functional-type
   spec-value: design-group
@@ -13,6 +17,10 @@ links:
   spec-key: non-functional-type
   spec-value: performance-runtime
   uid: non-functional
+- role: spec-refinement
+  spec-key: non-functional-type
+  spec-value: performance-runtime-limits
+  uid: non-functional
 - role: spec-refinement
   spec-key: non-functional-type
   spec-value: quality
diff --git a/rtemsspec/tests/spec/validation-more.yml b/rtemsspec/tests/spec/validation-more.yml
new file mode 100644
index 00000000..1b1858c8
--- /dev/null
+++ b/rtemsspec/tests/spec/validation-more.yml
@@ -0,0 +1,21 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2023 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: spec-member
+  uid: root
+- role: spec-refinement
+  spec-key: method
+  spec-value: by-inspection
+  uid: validation
+spec-description: null
+spec-example: null
+spec-info:
+  dict:
+    attributes: {}
+    description: null
+    mandatory-attributes: all
+spec-name: Validation More
+spec-type: validation-more
+type: spec
diff --git a/rtemsspec/tests/spec/validation.yml b/rtemsspec/tests/spec/validation.yml
new file mode 100644
index 00000000..3bc3c818
--- /dev/null
+++ b/rtemsspec/tests/spec/validation.yml
@@ -0,0 +1,24 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2023 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: spec-member
+  uid: root
+- role: spec-refinement
+  spec-key: type
+  spec-value: validation
+  uid: root
+spec-description: null
+spec-example: null
+spec-info:
+  dict:
+    attributes:
+      method:
+        description: null
+        spec-type: name
+    description: null
+    mandatory-attributes: all
+spec-name: Validation
+spec-type: validation
+type: spec
diff --git a/rtemsspec/tests/test_rtems.py b/rtemsspec/tests/test_rtems.py
index cdc40667..2d0a4980 100644
--- a/rtemsspec/tests/test_rtems.py
+++ b/rtemsspec/tests/test_rtems.py
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-2-Clause
 """ Unit tests for the rtemsspec.rtems module. """
 
-# Copyright (C) 2022 embedded brains GmbH & Co. KG
+# Copyright (C) 2022, 2023 embedded brains GmbH & Co. KG
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -26,9 +26,10 @@
 
 import pytest
 
-from rtemsspec.items import EmptyItemCache, Item
+from rtemsspec.items import EmptyItemCache, Item, ItemCache
 from rtemsspec.rtems import augment_with_test_links, is_pre_qualified, \
-    recursive_is_enabled
+    recursive_is_enabled, validate
+from rtemsspec.tests.util import create_item_cache_config_and_copy_spec
 
 
 def test_is_pre_qualified():
@@ -117,3 +118,10 @@ def test_recursive_is_enabled():
     item_cache.set_enabled([], recursive_is_enabled)
     assert d.enabled
     assert not e.enabled
+
+
+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"])
diff --git a/specview.py b/specview.py
index 9cef096c..3b220bd1 100755
--- a/specview.py
+++ b/specview.py
@@ -33,7 +33,7 @@ from typing import Any, Dict, List, Optional, Set, Tuple
 from rtemsspec.items import EmptyItem, Item, ItemCache, ItemMapper, \
     ItemGetValueContext
 from rtemsspec.rtems import augment_with_test_links, is_pre_qualified, \
-    recursive_is_enabled
+    recursive_is_enabled, validate
 from rtemsspec.sphinxcontent import SphinxContent
 from rtemsspec.transitionmap import Transition, TransitionMap
 from rtemsspec.util import load_config
@@ -169,72 +169,6 @@ def _view(item: Item, level: int, role: Optional[str],
         _view(link.item, level + 1, link.role, validated_filter)
 
 
-_VALIDATION_LEAF = [
-    "constraint",
-    "glossary/group",
-    "glossary/term",
-    "interface/domain",
-    "interface/enum",
-    "interface/enumerator",
-    "interface/forward-declaration",
-    "interface/header-file",
-    "interface/register-block",
-    "interface/struct",
-    "interface/typedef",
-    "interface/union",
-    "interface/unspecified-define",
-    "interface/unspecified-enum",
-    "interface/unspecified-enumerator",
-    "interface/unspecified-function",
-    "interface/unspecified-group",
-    "interface/unspecified-macro",
-    "interface/unspecified-object",
-    "interface/unspecified-struct",
-    "interface/unspecified-typedef",
-    "interface/unspecified-union",
-    "memory-benchmark",
-    "requirement/functional/action",
-    "requirement/non-functional/performance-runtime",
-    "runtime-measurement-test",
-    "test-case",
-    "validation/by-analysis",
-    "validation/by-inspection",
-    "validation/by-review-of-design",
-]
-
-_VALIDATION_ROLES = _CHILD_ROLES + ["validation"]
-
-
-def _validate_tree(item: Item) -> bool:
-    pre_qualified = is_pre_qualified(item)
-    item["_pre_qualified"] = pre_qualified
-    validated = True
-    count = 0
-    for link in itertools.chain(item.links_to_children(_VALIDATION_ROLES),
-                                item.links_to_parents(_PARENT_ROLES)):
-        validated = _validate_tree(link.item) and validated
-        count += 1
-    if count == 0:
-        validated = (not pre_qualified) or (item.type in _VALIDATION_LEAF)
-    item["_validated"] = validated
-    return validated
-
-
-def _validate_containers(item: Item) -> None:
-    for item_2 in itertools.chain(
-            item.cache.items_by_type["interface/domain"],
-            item.cache.items_by_type["interface/header-file"]):
-        for item_3 in item_2.children("interface-placement"):
-            if not item_3["_validated"]:
-                item_2["_validated"] = False
-                break
-
-
-def _validate(item: Item) -> None:
-    _validate_tree(item)
-    _validate_containers(item)
-
-
 def _validation_count(item: Item) -> int:
     return len(list(child for child in item.children("validation")))
 
@@ -466,7 +400,7 @@ def main() -> None:
     root = item_cache["/req/root"]
 
     if args.filter == "none":
-        _validate(root)
+        validate(root)
         _view(root, 0, None, args.validated)
     elif args.filter == "action-table":
         for uid in args.UIDs:
@@ -475,17 +409,17 @@ def main() -> None:
         for uid in args.UIDs:
             _action_list(item_cache[uid])
     elif args.filter == "orphan":
-        _validate(root)
+        validate(root)
         for item in item_cache.values():
             if item["type"] in ["build", "spec"]:
                 continue
             if item.enabled and "_validated" not in item:
                 print(item.uid)
     elif args.filter == "no-validation":
-        _validate(root)
+        validate(root)
         _no_validation(root, [])
     elif args.filter == "api":
-        _validate(root)
+        validate(root)
         _list_api(item_cache)
     elif args.filter == "design":
         _design(item_cache)



More information about the vc mailing list