Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions src/extensions/score_metamodel/checks/check_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,14 +273,24 @@ def check_extra_options(
log.warning_for_need(need, msg)


# Same pattern as the `valid_from`/`valid_until` options in metamodel.yaml:
# v<major>.<minor> with an optional .<patch>, no leading zeroes.
_MILESTONE_PATTERN = re.compile(r"v(0|[1-9]\d*)\.(0|[1-9]\d*)(\.(0|[1-9]\d*))?$")


def parse_milestone(value: str) -> tuple[int, int, int]:
"""Parse a string like 'v0.5' or 'v1.0.0'. No suffixes."""
match = re.match(r"v(\d+)(\.(\d+))?(\.(\d+))?$", value)
"""Parse a string like 'v0.5' or 'v1.0.0'. No suffixes.

Uses the same pattern as the `valid_from`/`valid_until` options in
metamodel.yaml, so values rejected by the option schema raise ValueError
and stay with pattern validation instead of being compared here.
"""
match = _MILESTONE_PATTERN.match(value)
if not match:
raise ValueError(f"Invalid milestone format: {value}")
major = int(match.group(1))
minor = int(match.group(3) or 0)
patch = int(match.group(5) or 0)
minor = int(match.group(2))
patch = int(match.group(4) or 0)
return (major, minor, patch)


Expand All @@ -303,8 +313,13 @@ def check_validity_consistency(
if not valid_from or not valid_until:
return

valid_from_version = parse_milestone(valid_from)
valid_until_version = parse_milestone(valid_until)
try:
valid_from_version = parse_milestone(valid_from)
valid_until_version = parse_milestone(valid_until)
except ValueError:
# Pattern validation reports malformed milestones separately.
return
Comment thread
a-zw marked this conversation as resolved.

if valid_from_version >= valid_until_version:
msg = (
"inconsistent validity: "
Expand Down
2 changes: 1 addition & 1 deletion src/extensions/score_metamodel/metamodel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,7 @@ graph_checks:
# req-Id: tool_req__docs_req_arch_link_safety_to_arch
tool_req__docs_req_arch_link_safety_to_arch:
needs:
include: feat_arc_sta, logic_arc_int, logic_arc_int_op, comp_arc_sta, real_arc_int, real_arc_int_op
include: feat_arc_sta, logic_arc_int, logic_arc_int_op, comp_arc_sta, real_arc_int, real_arc_int_op, comp
condition:
and:
- safety != QM
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
..
# *******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

.. test_metadata::
:id: test_metadata__arch_link_fulfils
:fully_verifies_list: tool_req__docs_arch_link_fulfils[version==3]
:test_type: requirements_based
:derivation_technique: requirements_based

Checks the allowed ``fulfils`` target type for each architecture source type.
Each permitted source-target combination is accepted, and mismatched feature
and component requirement targets are rejected.


.. feat:: Feature
:id: feat__arch_fulfils__feature
:security: NO
:safety: QM
:status: valid


.. comp:: Component
:id: comp__arch_fulfils__component
:security: NO
:safety: QM
:status: valid
:belongs_to: feat__arch_fulfils__feature


.. logic_arc_int:: Logical interface
:id: logic_arc_int__arch_fulfils__interface
:security: NO
:safety: QM
:status: valid
:included_by: feat__arch_fulfils__feature


.. feat_req:: Feature requirement
:id: feat_req__arch_fulfils__feature__good
:reqtype: Functional
:security: NO
:safety: QM
:status: valid
:valid_from: v1.0
:satisfied_by: feat__arch_fulfils__feature

A feature requirement target.


.. comp_req:: Component requirement
:id: comp_req__arch_fulfils__component__good
:reqtype: Functional
:security: NO
:safety: QM
:status: valid
:satisfied_by: comp__arch_fulfils__component

A component requirement target.


.. feat_arc_sta:: Feature static view fulfils feature requirement
:id: feat_arc_sta__arch_fulfils__good
:security: NO
:safety: QM
:status: valid
:belongs_to: feat__arch_fulfils__feature
:includes: logic_arc_int__arch_fulfils__interface
:fulfils: feat_req__arch_fulfils__feature__good
:expect_not: but it must reference


.. feat_arc_dyn:: Feature dynamic view fulfils feature requirement
:id: feat_arc_dyn__arch_fulfils__good
:security: NO
:safety: QM
:status: valid
:belongs_to: feat__arch_fulfils__feature
:fulfils: feat_req__arch_fulfils__feature__good
:expect_not: but it must reference


.. logic_arc_int:: Logical interface fulfils feature requirement
:id: logic_arc_int__arch_fulfils__fulfils_good
:security: NO
:safety: QM
:status: valid
:fulfils: feat_req__arch_fulfils__feature__good
:expect_not: but it must reference


.. comp_arc_sta:: Component static view fulfils component requirement
:id: comp_arc_sta__arch_fulfils__good
:security: NO
:safety: QM
:status: valid
:belongs_to: comp__arch_fulfils__component
:fulfils: comp_req__arch_fulfils__component__good
:expect_not: but it must reference


.. comp_arc_dyn:: Component dynamic view fulfils component requirement
:id: comp_arc_dyn__arch_fulfils__good
:security: NO
:safety: QM
:status: valid
:belongs_to: comp__arch_fulfils__component
:fulfils: comp_req__arch_fulfils__component__good
:expect_not: but it must reference


.. real_arc_int:: Real interface fulfils component requirement
:id: real_arc_int__arch_fulfils__good
:security: NO
:safety: QM
:status: valid
:language: cpp
:fulfils: comp_req__arch_fulfils__component__good
:expect_not: but it must reference


.. feat_arc_sta:: Feature static view rejects component requirement
:id: feat_arc_sta__arch_fulfils__bad
:security: NO
:safety: QM
:status: valid
:belongs_to: feat__arch_fulfils__feature
:includes: logic_arc_int__arch_fulfils__interface
:fulfils: comp_req__arch_fulfils__component__good
:expect: but it must reference Feature Requirement (feat_req)


.. comp_arc_sta:: Component static view rejects feature requirement
:id: comp_arc_sta__arch_fulfils__bad
:security: NO
:safety: QM
:status: valid
:belongs_to: comp__arch_fulfils__component
:fulfils: feat_req__arch_fulfils__feature__good
:expect: but it must reference Component Requirement (comp_req)


.. feat_arc_dyn:: Feature dynamic view rejects component requirement
:id: feat_arc_dyn__arch_fulfils__bad
:security: NO
:safety: QM
:status: valid
:belongs_to: feat__arch_fulfils__feature
:fulfils: comp_req__arch_fulfils__component__good
:expect: but it must reference Feature Requirement (feat_req)


.. logic_arc_int:: Logical interface rejects component requirement
:id: logic_arc_int__arch_fulfils__bad
:security: NO
:safety: QM
:status: valid
:fulfils: comp_req__arch_fulfils__component__good
:expect: but it must reference Feature Requirement (feat_req)


.. comp_arc_dyn:: Component dynamic view rejects feature requirement
:id: comp_arc_dyn__arch_fulfils__bad
:security: NO
:safety: QM
:status: valid
:belongs_to: comp__arch_fulfils__component
:fulfils: feat_req__arch_fulfils__feature__good
:expect: but it must reference Component Requirement (comp_req)


.. real_arc_int:: Real interface rejects feature requirement
:id: real_arc_int__arch_fulfils__bad
:security: NO
:safety: QM
:status: valid
:language: cpp
:fulfils: feat_req__arch_fulfils__feature__good
:expect: but it must reference Component Requirement (comp_req)
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
..
# *******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************


.. test_metadata:: Common description attribute
:id: test_metadata__common_attr_description
:partially_verifies_list: tool_req__docs_common_attr_description
:test_type: requirements_based
:derivation_technique: requirements_based

Checks that requirement types accept non-empty descriptions and reject a
missing description.


.. feat:: Feature target
:id: feat__description_target
:version: 1
:status: valid
:safety: QM
:security: NO


.. comp:: Component target
:id: comp__description_target
:version: 1
:status: valid
:safety: QM
:security: NO
:belongs_to: feat__description_target


.. stkh_req:: Requirement used as a tool requirement target
:id: stkh_req__description__abcd
:version: 1
:reqtype: Functional
:safety: QM
:security: NO
:status: valid
:rationale: fixture target
:valid_from: v1.0


.. feat_req:: Feature requirement with a description
:id: feat_req__description__aaaa
:version: 1
:reqtype: Functional
:safety: QM
:security: NO
:status: valid
:valid_from: v1.0
:satisfied_by: feat__description_target
:expect_not: is missing required attribute: `content`

This feature requirement has useful content.


.. feat_req:: Feature requirement without a description
:id: feat_req__description__aaab
:version: 1
:reqtype: Functional
:safety: QM
:security: NO
:status: valid
:valid_from: v1.0
:satisfied_by: feat__description_target
:expect: is missing required attribute: `content`


.. comp_req:: Component requirement with a description
:id: comp_req__description__aaaa
:version: 1
:reqtype: Functional
:safety: QM
:security: NO
:status: valid
:satisfied_by: comp__description_target
:expect_not: is missing required attribute: `content`

This component requirement has useful content.


.. comp_req:: Component requirement without a description
:id: comp_req__description__aaab
:version: 1
:reqtype: Functional
:safety: QM
:security: NO
:status: valid
:satisfied_by: comp__description_target
:expect: is missing required attribute: `content`


.. aou_req:: Assumption with a description
:id: aou_req__description__aaaa
:version: 1
:reqtype: Functional
:safety: QM
:security: NO
:status: valid
:expect_not: is missing required attribute: `content`

This assumption has useful content.


.. aou_req:: Assumption without a description
:id: aou_req__description__aaab
:version: 1
:reqtype: Functional
:safety: QM
:security: NO
:status: valid
:expect: is missing required attribute: `content`


.. tool_req:: Tool requirement with a description
:id: tool_req__description_valid
:version: 1
:satisfies: stkh_req__description__abcd
:expect_not: is missing required attribute: `content`

This tool requirement has useful content.


.. tool_req:: Tool requirement without a description
:id: tool_req__description_missing
:version: 1
:satisfies: stkh_req__description__abcd
:expect: is missing required attribute: `content`


.. gd_req:: Process requirement with a description
:id: gd_req__description_with
:version: 1
:expect_not: is missing required attribute: `content`

This process requirement has useful content.


.. gd_req:: Process requirement without a description
:id: gd_req__description_missing
:version: 1
:expect: is missing required attribute: `content`
Loading
Loading