diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 5b5eede8..9ae7a9de 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -118,6 +118,8 @@ jobs: generate-documents: name: ๐Ÿ“„ Documentation uses: ./.github/workflows/wc-document-generation.yml + with: + is-release: true permissions: contents: read @@ -140,7 +142,7 @@ jobs: - name: Upload documents to release run: | set -Eeuo pipefail - gh release upload "${REF_NAME}" ./*.pdf + gh release upload "${REF_NAME}" ./*.pdf ./*.sbdl env: GH_REPO: ${{ github.repository }} GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/wc-document-generation.yml b/.github/workflows/wc-document-generation.yml index e2d67e80..893dcc63 100644 --- a/.github/workflows/wc-document-generation.yml +++ b/.github/workflows/wc-document-generation.yml @@ -3,6 +3,11 @@ name: Document Generation on: workflow_call: + inputs: + is-release: + description: Whether the workflow is running for a release. + default: false + type: boolean permissions: {} @@ -22,19 +27,54 @@ jobs: - name: Install dependencies run: | set -Eeuo pipefail + sudo apt-get update && sudo apt-get install --no-install-recommends -y plantuml - python -m pip install gherkin-official==38.0.0 sbdl==1.21.3 + python -m pip install sbdl==1.22.7 - name: Build & Validate SBDL model - run: sbdl -m compile test/cpp/features/*.feature > amp-devcontainer.sbdl - - name: Generate SRS document - run: sbdl -m template-fill --template docs/templates/software-requirements-specification.md.j2 amp-devcontainer.sbdl > software-requirements-specification.md - - uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 + run: sbdl -m compile test/cpp/integration-tests.bats test/cpp/features/*.feature > amp-devcontainer.sbdl + - name: Create document control context + env: + GITHUB_REF_NAME: ${{ github.ref_name }} + IS_RELEASE: ${{ inputs.is-release }} + run: | + set -Eeuo pipefail + + cat > document-control.sbdl < software-requirements-specification.md + - name: ๐Ÿงช Generate STP document + run: sbdl -m template-fill --set-config template_extensions_file docs/templates/jinja-extensions.py --template docs/templates/software-test-plan.md.j2 amp-devcontainer.sbdl document-control.sbdl > software-test-plan.md + - name: ๐Ÿงฉ Generate RTM document + run: sbdl -m template-fill --set-config template_extensions_file docs/templates/jinja-extensions.py --template docs/templates/requirements-traceability-matrix.md.j2 amp-devcontainer.sbdl document-control.sbdl > requirements-traceability-matrix.md + - name: ๐Ÿ“„ Generate SRS PDF + uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 with: args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output software-requirements-specification.pdf software-requirements-specification.md + - name: ๐Ÿงช Generate STP PDF + uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 + with: + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output software-test-plan.pdf software-test-plan.md + - name: ๐Ÿงฉ Generate RTM PDF + uses: docker://pandoc/extra:3.9.0.0-ubuntu@sha256:72afa9c8d3300e5f10c9c4330e101725687f2179bffd912fb859c6d2ae85de62 + with: + args: --template eisvogel --syntax-highlighting idiomatic --number-sections --output requirements-traceability-matrix.pdf requirements-traceability-matrix.md - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: documents path: | *.pdf *.sbdl + !document-control.sbdl retention-days: 2 diff --git a/docs/templates/jinja-extensions.py b/docs/templates/jinja-extensions.py new file mode 100644 index 00000000..693a44ed --- /dev/null +++ b/docs/templates/jinja-extensions.py @@ -0,0 +1,9 @@ +from datetime import datetime + +def strftime_filter(value, fmt): + if value.endswith('Z'): + value = value[:-1] + '+00:00' + + return datetime.fromisoformat(value).strftime(fmt) + +filters = { 'strftime': strftime_filter } diff --git a/docs/templates/partials/document-control.md.j2 b/docs/templates/partials/document-control.md.j2 new file mode 100644 index 00000000..817e049c --- /dev/null +++ b/docs/templates/partials/document-control.md.j2 @@ -0,0 +1,7 @@ +| Property | Value | +|-------------------|---------------------------------------------------------------------------------------------------------------------------| +| Document version | {{ sbdl['doc_control']['custom:version'] }} | +| Generation date | {{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }} | +| Source revision | {{ sbdl['doc_control']['custom:git_sha'] }} | +| Source branch/tag | {{ sbdl['doc_control']['custom:git_ref'] }} | +| Model | SBDL {{ sbdl['doc_control']['custom:sbdl_compiler_version'] }} (DSL {{ sbdl['doc_control']['custom:sbdl_dsl_version'] }}) | diff --git a/docs/templates/partials/text-utilities.j2 b/docs/templates/partials/text-utilities.j2 new file mode 100644 index 00000000..8216b8e2 --- /dev/null +++ b/docs/templates/partials/text-utilities.j2 @@ -0,0 +1,15 @@ +{% macro reencode(text) -%} +{{ text.encode('utf-8').decode('unicode_escape') }} +{%- endmacro -%} + +{%- macro strip_gherkin_prefix(text) -%} +{{ text | replace('Rule: ', '') | replace('Feature: ', '') }} +{%- endmacro -%} + +{%- macro strip_bats_syntax(text) -%} +{{ text | replace('@test "', '') | replace('" \{', '') | replace('" {', '') }} +{%- endmacro -%} + +{%- macro display_short(text) -%} +{{ text[:60] }} +{%- endmacro %} diff --git a/docs/templates/requirements-traceability-matrix.md.j2 b/docs/templates/requirements-traceability-matrix.md.j2 new file mode 100644 index 00000000..00ad60ec --- /dev/null +++ b/docs/templates/requirements-traceability-matrix.md.j2 @@ -0,0 +1,115 @@ +--- +title: "Requirements traceability matrix for amp-devcontainer" +author: ["@rjaegers"] +colorlinks: true +date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" +keywords: [Traceability, Requirements, RTM, amp-devcontainer] +lang: "en" +titlepage: true +titlepage-color: "0B5ED7" +titlepage-text-color: "FFFFFF" +titlepage-rule-color: "FFFFFF" +titlepage-rule-height: 2 +toc: true +toc-own-page: true +header-includes: + - \AtEndDocument{\label{lastpage}} +{%- if sbdl['doc_control']['custom:is_release'] != 'true' %} +watermark: "DRAFT" +{%- endif %} +footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" +... + +{% import "partials/text-utilities.j2" as utils %} + +# Introduction + +## Purpose + +This document provides a requirements traceability matrix (RTM) for amp-devcontainer. It maps each requirement to its associated verification tests, providing evidence of test coverage across the system. + +## Abstract + +amp-devcontainer is a set of [devcontainers](https://containers.dev/) tailored towards modern, embedded, software development. This traceability matrix traces requirements from the *Software Requirements Specification (SRS)* to their corresponding verification tests as enumerated in the *Software Test Plan (STP)*. + +## Document Control + +{% include "partials/document-control.md.j2" with context %} + +This document is generated from a formal model defined in [sbdl](https://sbdl.dev) and versioned alongside the source code in Git. +The authoritative source of change history is the [Git log](https://github.com/philips-software/amp-devcontainer/commits/) of the source material from which the model is built. + +# Traceability Matrix +{%- for id, item in sbdl.items() %} +{%- if item.type == 'aspect' and 'custom:title' in item %} + +## {{ utils.reencode(utils.strip_gherkin_prefix(item['custom:title'])) }} + +| Requirement | Test | Status | +|-------------|------|--------| + +{%- if 'requirement' in item %} +{%- for req_ref in item.requirement %} +{%- set req = sbdl[req_ref.identifier] %} +{%- set req_name = utils.reencode(utils.strip_gherkin_prefix(req['custom:title'])) | trim %} + +{%- set ns_tests = namespace(test_list=[]) -%} + +{%- for test_id, test_elem in sbdl.items() -%} +{%- if test_elem.type == 'test' -%} +{%- if 'requirement' in test_elem -%} +{%- for test_req_ref in test_elem.requirement if test_req_ref.identifier == req_ref.identifier -%} +{%- set _ = ns_tests.test_list.append(test_id) -%} +{%- endfor -%} +{%- endif -%} +{%- endif -%} +{%- endfor -%} + +{%- if ns_tests.test_list -%} +{%- for test_id in ns_tests.test_list %} +{%- set test_name = utils.strip_bats_syntax(sbdl[test_id]['custom:title']) | trim %} +| {{ utils.display_short(req_name) }} | {{ test_id }}: {{ utils.display_short(test_name) }} | Traced | +{%- endfor -%} +{%- else %} +| {{ utils.display_short(req_name) }} | โ€” | **Not covered** | +{%- endif -%} + +{%- endfor %} +{%- endif %} +{%- endif %} +{%- endfor %} + +# Coverage Summary + +{%- set ns_summary = namespace(total_reqs=0, covered_reqs=0, total_tests=0) -%} + +{%- for elem_id, elem in sbdl.items() -%} +{%- if elem.type == 'requirement' -%} +{%- set ns_summary.total_reqs = ns_summary.total_reqs + 1 -%} + +{%- set ns_covered = namespace(is_covered=false) -%} +{%- for test_id, test_elem in sbdl.items() -%} +{%- if test_elem.type == 'test' and 'requirement' in test_elem -%} +{%- for req_ref in test_elem.requirement if req_ref.identifier == elem_id -%} +{%- set ns_covered.is_covered = true -%} +{%- endfor -%} +{%- endif -%} +{%- endfor -%} + +{%- if ns_covered.is_covered -%} +{%- set ns_summary.covered_reqs = ns_summary.covered_reqs + 1 -%} +{%- endif -%} + +{%- endif -%} + +{%- if elem.type == 'test' -%} +{%- set ns_summary.total_tests = ns_summary.total_tests + 1 -%} +{%- endif -%} +{%- endfor %} + +| Metric | Value | +|---|---| +| Total requirements | {{ ns_summary.total_reqs }} | +| Requirements with tests | {{ ns_summary.covered_reqs }} | +| Requirements without tests | {{ ns_summary.total_reqs - ns_summary.covered_reqs }} | +| Total tests | {{ ns_summary.total_tests }} | diff --git a/docs/templates/software-requirements-specification.md.j2 b/docs/templates/software-requirements-specification.md.j2 index 612884f6..b93bf0d5 100644 --- a/docs/templates/software-requirements-specification.md.j2 +++ b/docs/templates/software-requirements-specification.md.j2 @@ -2,7 +2,7 @@ title: "Software requirements specification for amp-devcontainer" author: ["@rjaegers"] colorlinks: true -date: "February-2026" +date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" keywords: [Software, Requirements, SRS, amp-devcontainer] lang: "en" titlepage: true @@ -12,14 +12,59 @@ titlepage-rule-color: "FFFFFF" titlepage-rule-height: 2 toc: true toc-own-page: true +header-includes: + - \AtEndDocument{\label{lastpage}} +{%- if sbdl['doc_control']['custom:is_release'] != 'true' %} +watermark: "DRAFT" +{%- endif %} +footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" ... +{% import "partials/text-utilities.j2" as utils %} + # Introduction ## Purpose This document describes the software system requirements for amp-devcontainer. +## Scope + +This document covers the requirements for the amp-devcontainer project: a set of devcontainers tailored towards modern, embedded, software development. + +The following is in scope: + +- Container image flavors for C++ and Rust development +- Tooling for compilation, debugging, static and dynamic analysis +- Compatibility with IDEs, container runtimes, and ci/cd systems +- Security properties of released container images +- Maintainability of the container images and their build system + +The following is out of scope: + +- Application-level software built using the containers +- Deployment of end-user products +- Requirements for third-party tools and dependencies included in the containers + +## References + +| Identifier | Title | +|------------|------------------------------------------------------------------------------------------------------------------------------------------| +| RFC 2119 | [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) | +| OCI | [Open Container Initiative Image Specification](https://github.com/opencontainers/image-spec/blob/main/spec.md) | +| SLSA | [Supply-chain Levels for Software Artifacts v1.0](https://slsa.dev/spec/v1.0/levels) | +| SemVer | [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html) | +| DevC | [Development Containers Specification](https://containers.dev/) | + +## Document Control + +{% include "partials/document-control.md.j2" with context %} + +This document is generated from a formal model defined in [sbdl](https://sbdl.dev) and versioned alongside the source code in Git. +The authoritative source of change history is the [Git log](https://github.com/philips-software/amp-devcontainer/commits/) of the source material from which the model is built. + +Changes to requirements are tracked at the individual requirement level through the version control system and are part of the project's standard change control process. + ## Definitions of key words The key words *MUST*, *MUST NOT*, *REQUIRED*, *SHALL*, *SHALL NOT*, *SHOULD*, *SHOULD NOT*, *RECOMMENDED*, *MAY*, and *OPTIONAL* in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119). @@ -42,30 +87,22 @@ The containers may be used both for local development and continuous integration # Requirements -{%- macro reencode(text) -%} -{{ text.encode('utf-8').decode('unicode_escape') }} -{%- endmacro -%} - -{%- macro strip_gherkin_prefix(text) -%} -{{ text | replace('Rule: ', '') | replace('Feature: ', '') }} -{%- endmacro -%} - -{%- for aspect_id, aspect in sbdl.items() %} -{%- if aspect.type == 'aspect' %} +{%- for id, item in sbdl.items() %} +{%- if item.type == 'aspect' and 'custom:title' in item %} -## {{ reencode(strip_gherkin_prefix(aspect['custom:title'])) }} +## {{ utils.reencode(utils.strip_gherkin_prefix(item['custom:title'])) }} -{{ reencode(aspect.description) }} +{{ utils.reencode(item.description) }} -{%- if 'requirement' in aspect %} -{%- for req_ref in aspect.requirement %} +{%- if 'requirement' in item %} +{%- for req_ref in item.requirement %} {%- set req = sbdl[req_ref.identifier] %} -### {{ req_ref.identifier }}: {{ reencode(strip_gherkin_prefix(req['custom:title'])) }} +### {{ req_ref.identifier }}: {{ utils.reencode(utils.strip_gherkin_prefix(req['custom:title'])) }} -{{ reencode(req.description) }} +{{ utils.reencode(req.description) }} -{{ reencode(req.remark) }} +{{ utils.reencode(req.remark) }} {%- endfor %} {%- endif %} diff --git a/docs/templates/software-test-plan.md.j2 b/docs/templates/software-test-plan.md.j2 new file mode 100644 index 00000000..3e473012 --- /dev/null +++ b/docs/templates/software-test-plan.md.j2 @@ -0,0 +1,122 @@ +--- +title: "Software test plan for amp-devcontainer" +author: ["@rjaegers"] +colorlinks: true +date: "{{ sbdl['doc_control']['custom:generated_at'] | strftime('%Y-%m-%d') }}" +keywords: [Software, Test, Plan, STP, amp-devcontainer] +lang: "en" +titlepage: true +titlepage-color: "0B5ED7" +titlepage-text-color: "FFFFFF" +titlepage-rule-color: "FFFFFF" +titlepage-rule-height: 2 +toc: true +toc-own-page: true +header-includes: + - \AtEndDocument{\label{lastpage}} +{%- if sbdl['doc_control']['custom:is_release'] != 'true' %} +watermark: "DRAFT" +{%- endif %} +footer-right: "\\thepage \\hspace{1pt} of \\pageref*{lastpage}" +... + +{% import "partials/text-utilities.j2" as utils %} + +# Introduction + +## Purpose + +This document describes the test plan for amp-devcontainer. +It defines the test strategy, methodology, and environment, and enumerates the tests that verify each requirement. + +For the full requirement descriptions, refer to the *Software Requirements Specification (SRS)*. +For the coverage overview, refer to the *Requirements Traceability Matrix (RTM)*. + +## Scope + +This document covers the following types of tests: + +- **Gherkin verification tests**: Scenario-based tests defined in Gherkin feature files and executed with Playwright. These tests verify behavioral requirements at the system level. +- **BATS integration tests**: Shell-based integration tests defined in BATS (Bash Automated Testing System) files. These tests verify tool availability, version alignment, and end-to-end compilation and analysis workflows. + +## References + +| Identifier | Title | +|------------|---------------------------------------------------------------------------------------------------------------------------------------| +| SRS | Software Requirements Specification for amp-devcontainer | +| RTM | Requirements Traceability Matrix for amp-devcontainer | +| RFC 2119 | [Key words for use in RFCs to Indicate Requirement Levels](https://www.rfc-editor.org/rfc/rfc2119) | + +## Document Control + +{% include "partials/document-control.md.j2" with context %} + +This document is generated from a formal model defined in [sbdl](https://sbdl.dev) and versioned alongside the source code in Git. +The authoritative source of change history is the [Git log](https://github.com/philips-software/amp-devcontainer/commits/) of the source material from which the model is built. + +## Definitions of key words + +The key words *MUST*, *MUST NOT*, *REQUIRED*, *SHALL*, *SHALL NOT*, *SHOULD*, *SHOULD NOT*, *RECOMMENDED*, *MAY*, and *OPTIONAL* in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119). + +# Test environment + +Tests are executed in a container built from the amp-devcontainer image. The container provides all necessary compilers, tools, and dependencies. + +| Component | Description | +|---|---| +| Container runtime | OCI-compatible container engine (e.g. Docker, Podman) | +| Gherkin test runner | Playwright with Gherkin step definitions | +| Integration test runner | BATS (Bash Automated Testing System) | +| CI platform | GitHub Actions | + +# Test methodology + +## Gherkin verification tests + +Gherkin scenarios follow the Given-When-Then structure. Each scenario exercises a specific capability of the devcontainer by automating interactions with the development environment. Tests are executed via Playwright inside a running devcontainer instance (GitHub Codespace or local). A scenario passes when all of its steps complete without error. + +## BATS integration tests + +BATS tests verify tool presence, version alignment, and end-to-end workflows (compilation, analysis, formatting) by executing shell commands inside the devcontainer. Each test function runs in isolation. A BATS test passes when the test function exits with code 0. + +## Expected results + +> **Note**: Structured expected-result data per test is not yet available in the current toolchain. This section will be extended when test result rendering is implemented. Currently, a test is considered passed when it completes without error as described above. + +# Tests by requirement area +{%- for id, item in sbdl.items() %} +{%- if item.type == 'aspect' and 'custom:title' in item %} + +## {{ utils.reencode(utils.strip_gherkin_prefix(item['custom:title'])) }} + +{%- if 'requirement' in item %} +{%- for req_ref in item.requirement %} +{%- set req = sbdl[req_ref.identifier] %} + +### {{ req_ref.identifier }}: {{ utils.reencode(utils.strip_gherkin_prefix(req['custom:title'])) }} + +{%- set ns_tests = namespace(has_tests=false) -%} + +{%- for test_id, test_elem in sbdl.items() -%} +{%- if test_elem.type == 'test' -%} +{%- if 'requirement' in test_elem -%} +{%- for test_req_ref in test_elem.requirement if test_req_ref.identifier == req_ref.identifier -%} +{%- set ns_tests.has_tests = true %} +- **{{ test_id }}**: {{ utils.reencode(utils.strip_bats_syntax(test_elem['custom:title'])) }} +{%- endfor -%} +{%- endif -%} +{%- endif -%} +{%- endfor -%} + +{%- if not ns_tests.has_tests %} +- *No tests traced to this requirement.* +{%- endif -%} + +{%- endfor %} +{%- endif %} +{%- endif %} +{%- endfor %} + +# Anomaly handling + +Test failures are tracked as issues in the project's issue tracker. Each failure is triaged, assigned a severity, and linked to the affected requirement(s). Resolution is verified by re-running the affected test(s). diff --git a/test/cpp/integration-tests.bats b/test/cpp/integration-tests.bats index 49a6f676..8c609626 100644 --- a/test/cpp/integration-tests.bats +++ b/test/cpp/integration-tests.bats @@ -80,6 +80,7 @@ teardown() { } @test "valid code input should result in working executable using host compiler" { + # @sbdl test-comp-0001 is test { custom:title is [[[[@-LINE]]]]; requirement is req-comp-0001 } cmake --preset gcc cmake --build --preset gcc @@ -89,6 +90,7 @@ teardown() { } @test "valid code input should result in elf executable using arm-none-eabi compiler" { + # @sbdl test-comp-0002 is test { custom:title is [[[[@-LINE]]]]; requirement is req-comp-0002 } cmake --preset gcc-arm-none-eabi cmake --build --preset gcc-arm-none-eabi @@ -98,6 +100,7 @@ teardown() { } @test "valid code input should result in Windows executable using clang-cl compiler" { + # @sbdl test-comp-0003 is test { custom:title is [[[[@-LINE]]]]; requirement is req-comp-0003 } install_win_sdk_when_ci_unset cmake --preset clang-cl @@ -113,21 +116,25 @@ teardown() { } @test "invalid code input should result in failing build" { + # @sbdl test-comp-0004 is test { custom:title is [[[[@-LINE]]]]; requirement is req-comp-0001 } cmake --preset gcc run ! cmake --build --preset gcc-fail } @test "using ccache as a compiler launcher should result in cached build using gcc compiler" { + # @sbdl test-comp-0005 is test { custom:title is [[[[@-LINE]]]]; requirement is req-comp-0004 } configure_and_build_with_ccache gcc } @test "using ccache as a compiler launcher should result in cached build using clang-cl compiler" { + # @sbdl test-comp-0006 is test { custom:title is [[[[@-LINE]]]]; requirement is req-comp-0004 } install_win_sdk_when_ci_unset configure_and_build_with_ccache clang-cl } @test "running clang-tidy as part of the build should result in warning diagnostics" { + # @sbdl test-sda-0001 is test { custom:title is [[[[@-LINE]]]]; requirement is req-sda-0002 } cmake --preset clang run cmake --build --preset clang-tidy @@ -136,6 +143,7 @@ teardown() { } @test "running include-what-you-use as part of the build should result in warning diagnostics" { + # @sbdl test-sda-0002 is test { custom:title is [[[[@-LINE]]]]; requirement is req-sda-0002 } cmake --preset clang run cmake --build --preset clang-iwyu @@ -144,12 +152,14 @@ teardown() { } @test "running clang-format should result in re-formatted code" { + # @sbdl test-sda-0003 is test { custom:title is [[[[@-LINE]]]]; requirement is req-sda-0001 } run clang-format clang-tools/unformatted.cpp assert_success assert_output "int main() {}" } @test "coverage information should be generated when running a testsuite" { + # @sbdl test-sda-0004 is test { custom:title is [[[[@-LINE]]]]; requirement is req-sda-0003 } cmake --preset coverage cmake --build --preset coverage @@ -162,7 +172,17 @@ teardown() { assert_output --partial "GCC Code Coverage Report" } +@test "a mutation score should be calculated when mutation testing a testsuite" { + # @sbdl test-sda-0005 is test { custom:title is [[[[@-LINE]]]]; requirement is req-sda-0004 } + cmake --preset mutation + cmake --build --preset mutation + + run ctest --preset mutation + assert_output --partial "[info] Mutation score:" +} + @test "crashes should be detected when fuzzing an executable" { + # @sbdl test-sda-0006 is test { custom:title is [[[[@-LINE]]]]; requirement is req-sda-0005 } cmake --preset clang cmake --build --preset fuzzing @@ -171,15 +191,8 @@ teardown() { assert_output --partial "SUMMARY: libFuzzer: deadly signal" } -@test "a mutation score should be calculated when mutation testing a testsuite" { - cmake --preset mutation - cmake --build --preset mutation - - run ctest --preset mutation - assert_output --partial "[info] Mutation score:" -} - @test "clangd should be able to analyze source files" { + # @sbdl test-sda-0007 is test { custom:title is [[[[@-LINE]]]]; requirement is req-sda-0002 } run clangd --check=gcc/main.cpp assert_success assert_output --partial "All checks completed, 0 errors"