diff --git a/strictdoc/core/file_traceability_index.py b/strictdoc/core/file_traceability_index.py index e97854752..40b1ea7ef 100644 --- a/strictdoc/core/file_traceability_index.py +++ b/strictdoc/core/file_traceability_index.py @@ -47,6 +47,7 @@ from strictdoc.helpers.cast import assert_cast from strictdoc.helpers.exception import StrictDocException from strictdoc.helpers.google_test import convert_function_name_to_gtest_macro +from strictdoc.helpers.mid import MID from strictdoc.helpers.ordered_set import OrderedSet if TYPE_CHECKING: @@ -601,15 +602,36 @@ def validate_and_resolve( continue assert source_node_.entity_name is not None + sdoc_node = None sdoc_node_uid = source_node_.get_sdoc_field( "UID", relevant_source_node_entry ) - if sdoc_node_uid is None: - sdoc_node_uid = f"{document_uid}/{path_to_source_file_}/{source_node_.entity_name}" - sdoc_node = traceability_index.get_node_by_uid_weak( - sdoc_node_uid + mid = source_node_.get_sdoc_field( + "MID", relevant_source_node_entry ) + # First merge criterion: Merge if SDoc node with same MID exists. + if mid is not None: + sdoc_node_mid = MID(mid) + merge_candidate_sdoc_node = ( + traceability_index.get_node_by_mid_weak(sdoc_node_mid) + ) + if isinstance(merge_candidate_sdoc_node, SDocNode): + sdoc_node = merge_candidate_sdoc_node + sdoc_node_uid = sdoc_node.reserved_uid + + if sdoc_node is None: + # If no UID from source code field or merge-by-MID, create UID by conventional scheme. + if sdoc_node_uid is None: + sdoc_node_uid = f"{document_uid}/{path_to_source_file_}/{source_node_.entity_name}" + # Second merge criterion: Merge if SDoc node with same UID exists. + tmp_sdoc_node = traceability_index.get_node_by_uid_weak( + sdoc_node_uid + ) + if isinstance(tmp_sdoc_node, SDocNode): + sdoc_node = tmp_sdoc_node + + assert sdoc_node_uid is not None if sdoc_node is not None: sdoc_node = assert_cast(sdoc_node, SDocNode) self.merge_sdoc_node_with_source_node( @@ -626,11 +648,6 @@ def validate_and_resolve( document, ) sdoc_node_uid = assert_cast(sdoc_node.reserved_uid, str) - traceability_index.graph_database.create_link( - link_type=GraphLinkType.UID_TO_NODE, - lhs_node=sdoc_node_uid, - rhs_node=sdoc_node, - ) if current_top_node is None: current_top_node = ( FileTraceabilityIndex.create_source_node_section( @@ -998,6 +1015,25 @@ def merge_sdoc_node_with_source_node( ) # Merge strategy: overwrite any field if there's a field with same name from custom tags. sdoc_node_fields = source_node.get_sdoc_fields(source_node_config_entry) + + # Sanity check: Nor UID neither MID must conflict (early auto-MID is allowed to be overwritten) + if ( + "MID" in sdoc_node.ordered_fields_lookup + and "MID" in sdoc_node_fields + ): + sdoc_mid_field = sdoc_node.get_field_by_name("MID").get_text_value() + if sdoc_mid_field != sdoc_node_fields["MID"]: + raise StrictDocException( + f"Can't merge node by UID {sdoc_node.reserved_uid}: " + f"Conflicting MID: {sdoc_mid_field} != {sdoc_node_fields['MID']}" + ) + if sdoc_node.reserved_uid is not None and "UID" in sdoc_node_fields: + if sdoc_node.reserved_uid != sdoc_node_fields["UID"]: + raise StrictDocException( + f"Can't merge node by MID {sdoc_node.reserved_mid}: " + f"Conflicting UID: {sdoc_node.reserved_uid} != {sdoc_node_fields['UID']}" + ) + FileTraceabilityIndex.set_sdoc_node_fields(sdoc_node, sdoc_node_fields) @staticmethod @@ -1081,6 +1117,45 @@ def connect_source_node_requirements( Here we link REQ and sdoc_node bidirectional. """ + if ( + sdoc_node.reserved_uid is not None + and not traceability_index.graph_database.has_link( + link_type=GraphLinkType.UID_TO_NODE, + lhs_node=sdoc_node.reserved_uid, + rhs_node=sdoc_node, + ) + ): + traceability_index.graph_database.create_link( + link_type=GraphLinkType.UID_TO_NODE, + lhs_node=sdoc_node.reserved_uid, + rhs_node=sdoc_node, + ) + + # A merge procedure may have overwritten the MID, + # in which case the graph database and search index needs an update. + if "MID" in sdoc_node.ordered_fields_lookup != sdoc_node.reserved_mid: + sdoc_mid_field = sdoc_node.get_field_by_name("MID").get_text_value() + if sdoc_mid_field != sdoc_node.reserved_mid: + # TODO: + # If we really want to support changing the auto-assigned MID, + # at least the graph database and the document search index need an update (remove old MID, add new MID). + # I currently struggle to update the search index. + parent_document = sdoc_node.get_parent_or_including_document() + sdoc_node.reserved_mid = MID(sdoc_mid_field) + if parent_document.config.enable_mid: + sdoc_node.mid_permanent = True + + if not traceability_index.graph_database.has_link( + link_type=GraphLinkType.MID_TO_NODE, + lhs_node=sdoc_node.reserved_mid, + rhs_node=sdoc_node, + ): + traceability_index.graph_database.create_link( + link_type=GraphLinkType.MID_TO_NODE, + lhs_node=sdoc_node.reserved_mid, + rhs_node=sdoc_node, + ) + for marker_ in source_node.markers: if not isinstance(marker_, FunctionRangeMarker): continue diff --git a/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/parent.sdoc b/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/parent.sdoc similarity index 100% rename from tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/parent.sdoc rename to tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/parent.sdoc diff --git a/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/source_node_base.sdoc b/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/source_node_base.sdoc similarity index 93% rename from tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/source_node_base.sdoc rename to tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/source_node_base.sdoc index 22caeec03..cd74e7c5b 100644 --- a/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/source_node_base.sdoc +++ b/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/source_node_base.sdoc @@ -39,7 +39,7 @@ ELEMENTS: TITLE: Merge example.c into static nodes [REQUIREMENT] -UID: SRC-NODES-BASE/src/example/example.c/example_1 +UID: SRC-NODES-BASE/src/example.c/example_1 TITLE: TITLE from sdoc FOO: FOO text from sdoc BAR: BAR text from sdoc diff --git a/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/src/example/example.c b/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/src/example.c similarity index 100% rename from tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/src/example/example.c rename to tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/src/example.c diff --git a/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/strictdoc.toml b/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/strictdoc.toml similarity index 100% rename from tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/strictdoc.toml rename to tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/strictdoc.toml diff --git a/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/test.itest b/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/test.itest new file mode 100644 index 000000000..37db9c53f --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_sdoc_by_default_uid/test.itest @@ -0,0 +1,30 @@ +# +# This test verifies that a source nodes is merged with a static SDoc node if +# - the source nodes is not marked up with a UID field (i.e., default UID is effective), and +# - static SDoc node was explicitly given the default UID. +# +# @relation(SDOC-SRS-141, scope=file) +# + +RUN: %strictdoc --debug export %S --output-dir %T | filecheck %s + +CHECK: Published: Hello world doc + +RUN: %check_exists --file "%T/html/_source_files/src/example.c.html" + +RUN: %cat %T/html/%THIS_TEST_FOLDER/source_node_base.html | filecheck %s --check-prefix CHECK-HTML +CHECK-HTML: Requirements from Source Nodes +CHECK-HTML: SRC-NODES-BASE/src/example.c/example_1 +CHECK-HTML: TITLE from sdoc +CHECK-HTML: class="requirement__link-parent" href="../30_merge_with_sdoc_by_default_uid/parent.html#REQ-1" +CHECK-HTML: src/example.c, lines: 3-14, function example_1() +CHECK-HTML-NOT: FOO text from sdoc +CHECK-HTML: FOO text from example.c +CHECK-HTML-NOT: BAR text from sdoc +CHECK-HTML: BAR text from example.c + +RUN: %cat %T/html/_source_files/src/example.c.html | filecheck %s --check-prefix CHECK-SOURCE-FILE +CHECK-SOURCE-FILE: SRC-NODES-BASE/src/example.c/example_1 + +RUN: %cat %T/html/source_coverage.html | filecheck %s --check-prefix CHECK-SOURCE-COVERAGE +CHECK-SOURCE-COVERAGE: 100.0 diff --git a/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/test.itest b/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/test.itest deleted file mode 100644 index edd3709f2..000000000 --- a/tests/integration/features/source_code_traceability/_source_nodes/30_merge_with_static_node/test.itest +++ /dev/null @@ -1,24 +0,0 @@ -# -# @relation(SDOC-SRS-141, scope=file) -# - -RUN: %strictdoc --debug export %S --output-dir %T | filecheck %s - -CHECK: Published: Hello world doc - -RUN: %check_exists --file "%T/html/_source_files/src/example/example.c.html" - -RUN: %cat %T/html/%THIS_TEST_FOLDER/source_node_base.html | filecheck %s --check-prefix CHECK-HTML -CHECK-HTML: Requirements from Source Nodes -CHECK-HTML: SRC-NODES-BASE/src/example/example.c/example_1 -CHECK-HTML: {{.*}}TITLE from sdoc -CHECK-HTML: class="requirement__link-parent" href="../30_merge_with_static_node/parent.html#REQ-1" -CHECK-HTML: src/example/example.c, lines: 3-14, function example_1() -CHECK-HTML: FOO text from example.c -CHECK-HTML: BAR text from example.c - -RUN: %cat %T/html/_source_files/src/example/example.c.html | filecheck %s --check-prefix CHECK-SOURCE-FILE -CHECK-SOURCE-FILE: SRC-NODES-BASE/src/example/example.c/example_1 - -RUN: %cat %T/html/source_coverage.html | filecheck %s --check-prefix CHECK-SOURCE-COVERAGE -CHECK-SOURCE-COVERAGE: 100.0 diff --git a/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/parent.sdoc b/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/parent.sdoc new file mode 100644 index 000000000..7eff27bf2 --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/parent.sdoc @@ -0,0 +1,17 @@ +[DOCUMENT] +TITLE: Hello world doc + +[REQUIREMENT] +UID: REQ-1 +TITLE: Requirement Title +STATEMENT: Requirement Statement + +[REQUIREMENT] +UID: REQ-2 +TITLE: Requirement Title #2 +STATEMENT: Requirement Statement #2 + +[REQUIREMENT] +UID: REQ-3 +TITLE: Requirement Title #3 +STATEMENT: Requirement Statement #3 diff --git a/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/source_node_base.sdoc b/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/source_node_base.sdoc new file mode 100644 index 000000000..b27f68bbc --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/source_node_base.sdoc @@ -0,0 +1,72 @@ +[DOCUMENT] +MID: c2d4542d5f1741c88dfcb4f68ad7dcbd +TITLE: Requirements from Source Nodes +UID: SRC-NODES-BASE + +[GRAMMAR] +ELEMENTS: +- TAG: SECTION + PROPERTIES: + IS_COMPOSITE: True + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + PROPERTIES: + VIEW_STYLE: Narrative + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: FOO + TYPE: String + REQUIRED: False + - TITLE: BAR + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + +[[SECTION]] +TITLE: Merge example.c into static nodes + +[REQUIREMENT] +UID: REQ-SOURCE-1 +TITLE: TITLE1 from sdoc +FOO: FOO1 text from sdoc +BAR: BAR1 text from sdoc +RELATIONS: +- TYPE: Parent + VALUE: REQ-1 + +[REQUIREMENT] +UID: REQ-SOURCE-2 +MID: 80cd685d-0e18-44b8-9842-c1863a2eb9ec +TITLE: TITLE2 from sdoc +FOO: FOO2 text from sdoc +BAR: BAR2 text from sdoc +RELATIONS: +- TYPE: Parent + VALUE: REQ-2 + +[REQUIREMENT] +UID: REQ-SOURCE-3 +TITLE: TITLE3 from sdoc +FOO: FOO3 text from sdoc +BAR: BAR3 text from sdoc +RELATIONS: +- TYPE: Parent + VALUE: REQ-3 + +[[/SECTION]] diff --git a/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/src/example.c b/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/src/example.c new file mode 100644 index 000000000..fa900f484 --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/src/example.c @@ -0,0 +1,48 @@ +#include + +/** + * Some text. + * + * @relation(REQ-1, scope=function) + * + * UID: REQ-SOURCE-1 + * + * FOO: FOO1 text from example.c + * + * BAR: BAR1 text from example.c + */ +void example_1(void) { + print("hello world\n"); +} + +/** + * Some text. + * + * @relation(REQ-2, scope=function) + * + * UID: REQ-SOURCE-2 + * + * FOO: FOO2 text from example.c + * + * BAR: BAR2 text from example.c + */ +void example_2(void) { + print("hello world\n"); +} + +/** + * Some text. + * + * @relation(REQ-3, scope=function) + * + * UID: REQ-SOURCE-3 + * + * MID: 1973a567-a109-491d-b7f0-6bb22eafa6ab + * + * FOO: FOO3 text from example.c + * + * BAR: BAR3 text from example.c + */ +void example_3(void) { + print("hello world\n"); +} diff --git a/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/strictdoc.toml b/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/strictdoc.toml new file mode 100644 index 000000000..f8688a0cd --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/strictdoc.toml @@ -0,0 +1,14 @@ +[project] + +features = [ + "REQUIREMENT_TO_SOURCE_TRACEABILITY", + "SOURCE_FILE_LANGUAGE_PARSERS", +] + +source_nodes = [ + { "src/" = { uid = "SRC-NODES-BASE", node_type = "REQUIREMENT" } } +] + +exclude_source_paths = [ + "test.itest" +] diff --git a/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/test.itest b/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/test.itest new file mode 100644 index 000000000..6c426ff6b --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/31_merge_with_sdoc_by_uid/test.itest @@ -0,0 +1,58 @@ +# +# This test verifies that a source nodes is merged with a static SDoc node with same explicit UID annotated. +# The following cases shall be handled: +# - If MID is set at neither side, a random (but hidden) automatic MID is assigned by StrictDoc. +# - If MID is set only at the sdoc side, the MID remains effective. +# - If MID is set only at the source side, early random automatic MID is overwritten by source side MID. +# +# Cases tested elsewhere: +# - If MID is set on both sides and is equal, this is considered "merge by mid". +# - If MID is set on both sides but is different, this is considered a validation error. +# +# @relation(SDOC-SRS-141, scope=file) +# + +RUN: %strictdoc --debug export %S --output-dir %T | filecheck %s + +CHECK: Published: Hello world doc + +RUN: %check_exists --file "%T/html/_source_files/src/example.c.html" + +RUN: %cat %T/html/%THIS_TEST_FOLDER/source_node_base.html | filecheck %s --check-prefix CHECK-HTML +CHECK-HTML: Requirements from Source Nodes +CHECK-HTML-NOT: SRC-NODES-BASE/src/example.c/example_1 +CHECK-HTML: REQ-SOURCE-1 +CHECK-HTML: TITLE1 from sdoc +CHECK-HTML: src/example.c, lines: 3-16, function example_1() +CHECK-HTML-NOT: FOO1 text from sdoc +CHECK-HTML: FOO1 text from example.c +CHECK-HTML-NOT: BAR1 text from sdoc +CHECK-HTML: BAR1 text from example.c + +CHECK-HTML-NOT: SRC-NODES-BASE/src/example.c/example_2 +CHECK-HTML: REQ-SOURCE-2 +CHECK-HTML: TITLE2 from sdoc +CHECK-HTML: src/example.c, lines: 18-31, function example_2() +CHECK-HTML-NOT: FOO2 text from sdoc +CHECK-HTML: FOO2 text from example.c +CHECK-HTML-NOT: BAR2 text from sdoc +CHECK-HTML: BAR2 text from example.c + +CHECK-HTML-NOT: SRC-NODES-BASE/src/example.c/example_3 +CHECK-HTML: REQ-SOURCE-3 +CHECK-HTML: TITLE3 from sdoc +CHECK-HTML: 1973a567-a109-491d-b7f0-6bb22eafa6ab +CHECK-HTML: src/example.c, lines: 33-48, function example_3() +CHECK-HTML-NOT: FOO3 text from sdoc +CHECK-HTML: FOO3 text from example.c +CHECK-HTML-NOT: BAR3 text from sdoc +CHECK-HTML: BAR3 text from example.c + +RUN: %cat %T/html/_source_files/src/example.c.html | filecheck %s --check-prefix CHECK-SOURCE-FILE +CHECK-HTML-NOT: SRC-NODES-BASE/src/example.c/example_1 +CHECK-SOURCE-FILE: REQ-SOURCE-1 +CHECK-SOURCE-FILE: REQ-SOURCE-2 +CHECK-SOURCE-FILE: REQ-SOURCE-3 + +RUN: %cat %T/html/source_coverage.html | filecheck %s --check-prefix CHECK-SOURCE-COVERAGE +CHECK-SOURCE-COVERAGE: 100.0 diff --git a/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/parent.sdoc b/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/parent.sdoc new file mode 100644 index 000000000..278b98a77 --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/parent.sdoc @@ -0,0 +1,12 @@ +[DOCUMENT] +TITLE: Hello world doc + +[REQUIREMENT] +UID: REQ-1 +TITLE: Requirement Title +STATEMENT: Requirement Statement + +[REQUIREMENT] +UID: REQ-2 +TITLE: Requirement Title #2 +STATEMENT: Requirement Statement #2 diff --git a/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/source_node_base.sdoc b/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/source_node_base.sdoc new file mode 100644 index 000000000..c6c84f958 --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/source_node_base.sdoc @@ -0,0 +1,54 @@ +[DOCUMENT] +MID: c2d4542d5f1741c88dfcb4f68ad7dcbd +TITLE: Requirements from Source Nodes +UID: SRC-NODES-BASE + +[GRAMMAR] +ELEMENTS: +- TAG: SECTION + PROPERTIES: + IS_COMPOSITE: True + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + PROPERTIES: + VIEW_STYLE: Narrative + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: FOO + TYPE: String + REQUIRED: False + - TITLE: BAR + TYPE: String + REQUIRED: False + RELATIONS: + - TYPE: Parent + - TYPE: File + +[[SECTION]] +TITLE: Merge example.c into static nodes + +[REQUIREMENT] +UID: REQ-SOURCE-1 +MID: 3bd0162d-d6d2-42a1-9324-ab8415190970 +TITLE: TITLE from sdoc +FOO: FOO text from sdoc +BAR: BAR text from sdoc +RELATIONS: +- TYPE: Parent + VALUE: REQ-1 + +[[/SECTION]] diff --git a/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/src/example.c b/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/src/example.c new file mode 100644 index 000000000..0fe5bf23e --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/src/example.c @@ -0,0 +1,16 @@ +#include + +/** + * Some text. + * + * @relation(REQ-1, scope=function) + * + * MID: 3bd0162d-d6d2-42a1-9324-ab8415190970 + * + * FOO: FOO text from example.c + * + * BAR: BAR text from example.c + */ +void example_1(void) { + print("hello world\n"); +} diff --git a/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/strictdoc.toml b/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/strictdoc.toml new file mode 100644 index 000000000..f8688a0cd --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/strictdoc.toml @@ -0,0 +1,14 @@ +[project] + +features = [ + "REQUIREMENT_TO_SOURCE_TRACEABILITY", + "SOURCE_FILE_LANGUAGE_PARSERS", +] + +source_nodes = [ + { "src/" = { uid = "SRC-NODES-BASE", node_type = "REQUIREMENT" } } +] + +exclude_source_paths = [ + "test.itest" +] diff --git a/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/test.itest b/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/test.itest new file mode 100644 index 000000000..aefd72bf4 --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/32_merge_with_sdoc_by_mid/test.itest @@ -0,0 +1,34 @@ +# +# This test verifies that a source nodes is merged with a static SDoc node with same explicit MID annotated. +# The following case shall be handled: +# - If MID is set and equal at both sides and no UID update is required, merge the node. +# +# Cases tested elsewhere: +# - If MID is set and equal on both sides but UID update would be required, this is considered a validation error. +# +# @relation(SDOC-SRS-141, scope=file) +# + +RUN: %strictdoc --debug export %S --output-dir %T | filecheck %s + +CHECK: Published: Hello world doc + +RUN: %check_exists --file "%T/html/_source_files/src/example.c.html" + +RUN: %cat %T/html/%THIS_TEST_FOLDER/source_node_base.html | filecheck %s --check-prefix CHECK-HTML +CHECK-HTML: Requirements from Source Nodes +CHECK-HTML-NOT: SRC-NODES-BASE/src/example.c/example_1 +CHECK-HTML: 3bd0162d-d6d2-42a1-9324-ab8415190970 +CHECK-HTML: TITLE from sdoc +CHECK-HTML: src/example.c, lines: 3-16, function example_1() +CHECK-HTML-NOT: FOO text from sdoc +CHECK-HTML: FOO text from example.c +CHECK-HTML-NOT: BAR text from sdoc +CHECK-HTML: BAR text from example.c + +RUN: %cat %T/html/_source_files/src/example.c.html | filecheck %s --check-prefix CHECK-SOURCE-FILE +CHECK-HTML-NOT: SRC-NODES-BASE/src/example.c/example_1 +CHECK-SOURCE-FILE: 3bd0162d-d6d2-42a1-9324-ab8415190970 + +RUN: %cat %T/html/source_coverage.html | filecheck %s --check-prefix CHECK-SOURCE-COVERAGE +CHECK-SOURCE-COVERAGE: 100.0 diff --git a/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/source_node_base.sdoc b/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/source_node_base.sdoc new file mode 100644 index 000000000..e00351a94 --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/source_node_base.sdoc @@ -0,0 +1,48 @@ +[DOCUMENT] +MID: c2d4542d5f1741c88dfcb4f68ad7dcbd +TITLE: Requirements from Source Nodes +UID: SRC-NODES-BASE + +[GRAMMAR] +ELEMENTS: +- TAG: SECTION + PROPERTIES: + IS_COMPOSITE: True + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + PROPERTIES: + VIEW_STYLE: Narrative + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: FOO + TYPE: String + REQUIRED: False + - TITLE: BAR + TYPE: String + REQUIRED: False + +[[SECTION]] +TITLE: Merge example.c into static nodes + +[REQUIREMENT] +UID: REQ-SOURCE-1 +MID: 3bd0162d-d6d2-42a1-9324-ab8415190970 +TITLE: TITLE from sdoc +FOO: FOO text from sdoc +BAR: BAR text from sdoc + +[[/SECTION]] diff --git a/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/src/example.c b/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/src/example.c new file mode 100644 index 000000000..fcc707090 --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/src/example.c @@ -0,0 +1,14 @@ +#include + +/** + * UID: REQ-SOURCE-1 + * + * MID: e7c09b63-2bed-4046-9511-a5b17978f152 + * + * FOO: FOO text from example.c + * + * BAR: BAR text from example.c + */ +void example_1(void) { + print("hello world\n"); +} diff --git a/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/strictdoc.toml b/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/strictdoc.toml new file mode 100644 index 000000000..f8688a0cd --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/strictdoc.toml @@ -0,0 +1,14 @@ +[project] + +features = [ + "REQUIREMENT_TO_SOURCE_TRACEABILITY", + "SOURCE_FILE_LANGUAGE_PARSERS", +] + +source_nodes = [ + { "src/" = { uid = "SRC-NODES-BASE", node_type = "REQUIREMENT" } } +] + +exclude_source_paths = [ + "test.itest" +] diff --git a/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/test.itest b/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/test.itest new file mode 100644 index 000000000..bc72f832e --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/_validation/03_merge_by_uid_conflicting_mid/test.itest @@ -0,0 +1,9 @@ +# +# This test verifies that if SDoc node and source node have same UID and thus are +# subject to be merged, an error is thrown if both sides set also MID and the MIDs are not equal. +# +# @relation(SDOC-SRS-141, scope=file) +# + +RUN: %expect_exit 1 %strictdoc export %S --output-dir %T | filecheck %s --dump-input=fail +CHECK: error: Can't merge node by UID REQ-SOURCE-1: Conflicting MID: 3bd0162d-d6d2-42a1-9324-ab8415190970 != e7c09b63-2bed-4046-9511-a5b17978f152 diff --git a/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/source_node_base.sdoc b/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/source_node_base.sdoc new file mode 100644 index 000000000..e00351a94 --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/source_node_base.sdoc @@ -0,0 +1,48 @@ +[DOCUMENT] +MID: c2d4542d5f1741c88dfcb4f68ad7dcbd +TITLE: Requirements from Source Nodes +UID: SRC-NODES-BASE + +[GRAMMAR] +ELEMENTS: +- TAG: SECTION + PROPERTIES: + IS_COMPOSITE: True + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: True +- TAG: REQUIREMENT + PROPERTIES: + VIEW_STYLE: Narrative + FIELDS: + - TITLE: UID + TYPE: String + REQUIRED: False + - TITLE: MID + TYPE: String + REQUIRED: False + - TITLE: TITLE + TYPE: String + REQUIRED: False + - TITLE: FOO + TYPE: String + REQUIRED: False + - TITLE: BAR + TYPE: String + REQUIRED: False + +[[SECTION]] +TITLE: Merge example.c into static nodes + +[REQUIREMENT] +UID: REQ-SOURCE-1 +MID: 3bd0162d-d6d2-42a1-9324-ab8415190970 +TITLE: TITLE from sdoc +FOO: FOO text from sdoc +BAR: BAR text from sdoc + +[[/SECTION]] diff --git a/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/src/example.c b/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/src/example.c new file mode 100644 index 000000000..02a01bd76 --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/src/example.c @@ -0,0 +1,14 @@ +#include + +/** + * UID: REQ-SOURCE-2 + * + * MID: 3bd0162d-d6d2-42a1-9324-ab8415190970 + * + * FOO: FOO text from example.c + * + * BAR: BAR text from example.c + */ +void example_1(void) { + print("hello world\n"); +} diff --git a/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/strictdoc.toml b/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/strictdoc.toml new file mode 100644 index 000000000..f8688a0cd --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/strictdoc.toml @@ -0,0 +1,14 @@ +[project] + +features = [ + "REQUIREMENT_TO_SOURCE_TRACEABILITY", + "SOURCE_FILE_LANGUAGE_PARSERS", +] + +source_nodes = [ + { "src/" = { uid = "SRC-NODES-BASE", node_type = "REQUIREMENT" } } +] + +exclude_source_paths = [ + "test.itest" +] diff --git a/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/test.itest b/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/test.itest new file mode 100644 index 000000000..48cb05075 --- /dev/null +++ b/tests/integration/features/source_code_traceability/_source_nodes/_validation/04_merge_by_mid_conflicting_uid/test.itest @@ -0,0 +1,9 @@ +# +# This test verifies that if SDoc node and source node have same MID and thus are +# subject to be merged, an error is thrown if both sides set also UID and the UID are not equal. +# +# @relation(SDOC-SRS-141, scope=file) +# + +RUN: %expect_exit 1 %strictdoc export %S --output-dir %T | filecheck %s --dump-input=fail +CHECK: error: Can't merge node by MID 3bd0162d-d6d2-42a1-9324-ab8415190970: Conflicting UID: REQ-SOURCE-1 != REQ-SOURCE-2