diff --git a/.github/workflows/build-and-push-demo-pipeline.yaml b/.github/workflows/build-and-push-demo-pipeline.yaml
new file mode 100644
index 00000000..e0662150
--- /dev/null
+++ b/.github/workflows/build-and-push-demo-pipeline.yaml
@@ -0,0 +1,44 @@
+name: Build and push demo pipeline image
+
+on:
+ schedule:
+ - cron: '0 4 * * *' # 04:00 AM UTC every day
+
+jobs:
+ build-and-push-demo:
+ runs-on: ubuntu-22.04
+
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+ with:
+ ref: develop # @TODO remove it later
+
+ - name: Get current date
+ id: date
+ run: echo "DATE=$(date +'%Y%m%d')" >> $GITHUB_ENV
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Log in to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: docker/Dockerfile.linux
+ push: true
+ target: demo_pipeline
+ tags: |
+ ghcr.io/${{ github.repository_owner }}/qc-framework:demo-pipeline-latest
+ ghcr.io/${{ github.repository_owner }}/qc-framework:demo-pipeline-${{ env.DATE }}
diff --git a/.github/workflows/build-on-change-linux-bare.yaml b/.github/workflows/build-on-change-linux-bare.yaml
new file mode 100644
index 00000000..0430faf1
--- /dev/null
+++ b/.github/workflows/build-on-change-linux-bare.yaml
@@ -0,0 +1,113 @@
+name: Build framework on Linux Bare
+
+on:
+ # execute on every PR made targeting the branches bellow
+ pull_request:
+ branches:
+ - main
+ - develop # can be removed on main merge
+ paths: # we only include paths critical for building to avoid unnecessary runs
+ - src/**
+ - include/**
+ - scripts/cmake/**
+ - test/**
+ - .github/workflows/**
+ - doc/**
+ - runtime/**
+ - docker/**
+
+ # execute on every push made targeting the branches bellow
+ push:
+ branches:
+ - main
+ - develop # can be removed on main merge
+ paths: # we only include paths critical for building to avoid unnecessary runs
+ - src/**
+ - include/**
+ - scripts/cmake/**
+ - test/**
+ - .github/workflows/**
+ - doc/**
+ - runtime/**
+ - docker/**
+
+jobs:
+ build-linux:
+ runs-on: ubuntu-22.04
+ env:
+ TEST_ENABLED: ${{ github.event_name == 'pull_request' && 'ON' || 'OFF' }}
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Create dependencies build space
+ run: mkdir dependencies
+ shell: bash
+
+ - name: Install dependencies
+ working-directory: dependencies
+ run: |
+ echo "Installing Dependencies..."
+ sudo apt update
+ sudo apt install \
+ g++ \
+ g++-10 \
+ make \
+ build-essential \
+ cmake \
+ libgtest-dev \
+ qtbase5-dev \
+ libqt5xmlpatterns5-dev \
+ libxerces-c-dev \
+ pkg-config
+ echo "Dependencies installed."
+ shell: bash
+
+ - name: Build framework
+ # Currently this is building without the XSD file. If we want to expose
+ # the build artifact after, we might as well need to add the XSD file.
+ run: |
+ echo Building framework...
+ cmake -G "Unix Makefiles" -B./build -S . \
+ -DCMAKE_INSTALL_PREFIX="/home/$(whoami)/qc-build" \
+ -DENABLE_FUNCTIONAL_TESTS=$TEST_ENABLED -DXERCES_ROOT="/usr" \
+ -DQt5_DIR="/usr/lib/x86_64-linux-gnu/cmake/Qt5/" \
+ -DQt5XmlPatterns_DIR="/usr/lib/x86_64-linux-gnu/cmake/Qt5XmlPatterns/"
+ cmake --build ./build --target install --config Release -j4
+ cmake --install ./build
+ echo Done.
+ shell: bash
+
+ - name: Unit test execution
+ if: github.event_name == 'pull_request'
+ run: |
+ echo Starting tests...
+
+ ctest --test-dir build -C Release
+
+ echo All tests done.
+ shell: bash
+
+ - name: Archive test results
+ if: github.event_name == 'pull_request' && (success() || failure())
+ uses: actions/upload-artifact@v4
+ with:
+ name: unit-test-report
+ path: ${{ github.workspace }}/build/Testing/Temporary/LastTest.log
+
+ - name: Runtime test execution
+ if: github.event_name == 'pull_request'
+ run: |
+ mv build out_build
+ cp -r /home/$(whoami)/qc-build/bin bin
+ cp out_build/examples/checker_bundle_example/DemoCheckerBundle bin/
+ cd runtime
+ python3 -m pip install -r requirements.txt
+ python3 -m pytest -rA > runtime_test.log
+
+ - name: Archive runtime test results
+ if: github.event_name == 'pull_request' && (success() || failure())
+ uses: actions/upload-artifact@v4
+ with:
+ name: runtime-test-report
+ path: ${{ github.workspace }}/runtime/runtime_test.log
diff --git a/.github/workflows/build-on-change-linux.yaml b/.github/workflows/build-on-change-linux-docker.yaml
similarity index 87%
rename from .github/workflows/build-on-change-linux.yaml
rename to .github/workflows/build-on-change-linux-docker.yaml
index e03b885f..f682c0a1 100644
--- a/.github/workflows/build-on-change-linux.yaml
+++ b/.github/workflows/build-on-change-linux-docker.yaml
@@ -1,16 +1,16 @@
-name: Build framework on Linux
+name: Build framework on Linux Docker
on:
# execute on every PR made targeting the branches bellow
pull_request:
branches:
- - master
- - develop # can be removed on master merge
+ - main
+ - develop # can be removed on main merge
paths: # we only include paths critical for building to avoid unnecessary runs
- src/**
- include/**
- scripts/cmake/**
- - tests/**
+ - test/**
- .github/workflows/**
- doc/**
- runtime/**
@@ -19,12 +19,13 @@ on:
# execute on every push made targeting the branches bellow
push:
branches:
- - master
- - develop # can be removed on master merge
+ - main
+ - develop # can be removed on main merge
paths: # we only include paths critical for building to avoid unnecessary runs
- src/**
- include/**
- scripts/cmake/**
+ - test/**
- .github/workflows/**
- doc/**
- runtime/**
@@ -39,9 +40,9 @@ jobs:
- name: Docker Build
run: |
- docker build -f docker/Dockerfile.linux --target unit_test -t unit_test .
- docker build -f docker/Dockerfile.linux --target runtime_test -t runtime_test .
-
+ docker build -f docker/Dockerfile.linux --target unit_test -t unit_test .
+ docker build -f docker/Dockerfile.linux --target runtime_test -t runtime_test .
+
- name: Unit test execution
if: github.event_name == 'pull_request'
run: |
@@ -53,16 +54,15 @@ jobs:
with:
name: unit-test-report
path: ${{ github.workspace }}/LastTest.log
-
+
- name: Runtime test execution
if: github.event_name == 'pull_request'
run: |
docker run -v ${{ github.workspace }}:/out --rm --name runtime_test runtime_test
-
+
- name: Archive runtime test results
if: github.event_name == 'pull_request' && (success() || failure())
uses: actions/upload-artifact@v4
with:
name: runtime-test-report
path: ${{ github.workspace }}/runtime_test.log
-
diff --git a/.github/workflows/build-on-change-windows.yaml b/.github/workflows/build-on-change-windows.yaml
index 19f5a70e..8e686d05 100644
--- a/.github/workflows/build-on-change-windows.yaml
+++ b/.github/workflows/build-on-change-windows.yaml
@@ -4,8 +4,8 @@ on:
# execute on every PR made targeting the branches bellow
pull_request:
branches:
- - master
- - develop # can be removed on master merge
+ - main
+ - develop # can be removed on main merge
paths: # we only include paths critical for building to avoid unnecessary runs
- src/**
- include/**
@@ -19,12 +19,13 @@ on:
# execute on every push made targeting the branches bellow
push:
branches:
- - master
- - develop # can be removed on master merge
+ - main
+ - develop # can be removed on main merge
paths: # we only include paths critical for building to avoid unnecessary runs
- src/**
- include/**
- scripts/cmake/**
+ - test/**
- .github/workflows/**
- doc/**
- runtime/**
@@ -124,7 +125,7 @@ jobs:
Write-Output "All unit tests done."
shell: pwsh
-
+
- name: Archive test results
if: github.event_name == 'pull_request' && (success() || failure())
uses: actions/upload-artifact@v4
@@ -138,15 +139,12 @@ jobs:
Write-Output "Starting runtime tests..."
Rename-Item -path "$env:WORKING_PATH\qc-framework\qc-framework\build" -NewName "$env:WORKING_PATH\qc-framework\qc-framework\out_build"
- Copy-Item -Path "$env:WORKING_PATH\QC-Framework-Out" -Destination "$env:WORKING_PATH\qc-framework\qc-framework\build" -Recurse
- Copy-Item -Path "$env:WORKING_PATH\qc-framework\qc-framework\out_build\examples\checker_bundle_example\Release\DemoCheckerBundle.exe" -Destination "$env:WORKING_PATH\qc-framework\qc-framework\build\bin"
-
+ Copy-Item -Path "$env:WORKING_PATH\QC-Framework-Out\bin" -Destination "$env:WORKING_PATH\qc-framework\qc-framework\bin" -Recurse
+ Copy-Item -Path "$env:WORKING_PATH\qc-framework\qc-framework\out_build\examples\checker_bundle_example\Release\DemoCheckerBundle.exe" -Destination "$env:WORKING_PATH\qc-framework\qc-framework\bin"
+
cd "$env:WORKING_PATH\qc-framework\qc-framework\runtime"
python3 -m pip install -r requirements.txt
python3 -m pytest
Write-Output "All runtime tests done."
shell: pwsh
-
-
-
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 00000000..036def72
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,15 @@
+repos:
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.3.0
+ hooks:
+ - id: trailing-whitespace
+ - id: end-of-file-fixer
+ - id: no-commit-to-branch
+ args: [--branch=main]
+
+ - repo: https://github.com/pre-commit/mirrors-clang-format
+ rev: v16.0.6
+ hooks:
+ - id: clang-format
+ files: \.(c|cc|cxx|cpp|h|hpp|hxx)$
+ args: ["--style=file", "-i"]
diff --git a/README.md b/README.md
index d7226703..b0316cd6 100644
--- a/README.md
+++ b/README.md
@@ -74,6 +74,17 @@ An architecture overview and documentation is provided in the
# Getting Started
+## Using Docker-based demo pipeline
+
+A [Docker-based demo pipeline](demo_pipeline/README.md) is provided to help users try out the latest development
+of the framework, as well as the [OpenDrive](https://github.com/asam-ev/qc-opendrive/tree/develop)
+and [OpenScenario XML](https://github.com/asam-ev/qc-openscenarioxml/tree/develop) checker bundles.
+
+## Build the framework locally
+
+As the framework is still under development, it is not recommended to build
+it locally. A complete build instruction will be available in the near future.
+
The software can be build for Windows and Linux. Currently there are no
pre-built binaries available for the framework. Follow the [build
instructions](INSTALL.md) to create a runnable binary on your machine.
diff --git a/demo_pipeline/README.md b/demo_pipeline/README.md
new file mode 100644
index 00000000..36b13af1
--- /dev/null
+++ b/demo_pipeline/README.md
@@ -0,0 +1,82 @@
+# Demo pipeline
+
+The demo pipeline allow users to process OpenDRIVE and OpenSCENARIO XML files with respecting checkers and inspect the resulting `xqar` and `txt` files.
+
+### Download and run
+
+The demo pipeline is provided as a public Docker image in the Github container registry.
+
+To process a file, the `docker run` command below can be used and the following information can be specified:
+- The input folder which contains the input file.
+- The name the input file.
+- The output folder where the output files can be saved.
+
+```
+docker run \
+ -e INPUT_FILENAME=YOUR_INPUT_FILENAME \
+ -v YOUR_INPUT_FOLDER:/input_directory \
+ -v YOUR_OUTPUT_FOLDER:/out \
+ -e USER_ID=$(id -u) \
+ -e GROUP_ID=$(id -g) \
+ --rm --name demo_pipeline ghcr.io/asam-ev/qc-framework:demo-pipeline-latest
+```
+
+E.g. To process the file at `/home/user/xodr_files/test_ramp.xosc`
+
+```
+docker run \
+ -e INPUT_FILENAME=test_ramp.xosc \
+ -v /home/user/xodr_files:/input_directory \
+ -v /home/user/output:/out \
+ -e USER_ID=$(id -u) \
+ -e GROUP_ID=$(id -g) \
+ --rm --name demo_pipeline ghcr.io/asam-ev/qc-framework:demo-pipeline-latest
+```
+
+Alternatively, you can go to the input folder and execute the following command, which requires only the input file name to be specified. The output will be saved in the same folder.
+
+```
+cd /home/user/xodr_files
+
+docker run \
+ -e INPUT_FILENAME=test_ramp.xosc \
+ -v $(pwd):/input_directory \
+ -v $(pwd):/out \
+ -e USER_ID=$(id -u) \
+ -e GROUP_ID=$(id -g) \
+ --rm --name demo_pipeline ghcr.io/asam-ev/qc-framework:demo-pipeline-latest
+```
+
+The docker image will automatically:
+- Detect the type of file passed as input.
+- Create the specific config according to [config schema](../doc/schema/config_format.xsd).
+- Execute the runtime with specific checker, result pooling and text result application.
+
+Currently the demo_pipeline will clone and execute:
+
+- [OpenDRIVE checker @ develop branch](https://github.com/asam-ev/qc-opendrive/tree/develop)
+- [OpenSCENARIO XML checker @ develop branch](https://github.com/asam-ev/qc-openscenarioxml/tree/develop)
+
+After the execution, in the specified output folder you will find:
+
+- Specific CheckerBundle `xqar` result file.
+- ResultPooling `Result.xqar` result file.
+- TextReport `Report.txt` text file.
+
+Some OpenDrive and OpenScenario XML test files are available to try out.
+- [OpenDrive test files](https://github.com/asam-ev/qc-opendrive/tree/develop/tests/data)
+- [OpenScenario XML test files](https://github.com/asam-ev/qc-openscenarioxml/tree/develop/tests/data)
+
+### Local build instructions
+
+In case of local build of demo_pipeline docker image, you can execute:
+
+```
+cd ..
+
+DOCKER_BUILDKIT=1 \
+ docker build \
+ -f docker/Dockerfile.linux \
+ --target demo_pipeline \
+ -t demo_pipeline .
+```
diff --git a/demo_pipeline/configuration_generator.py b/demo_pipeline/configuration_generator.py
new file mode 100644
index 00000000..d49e22f9
--- /dev/null
+++ b/demo_pipeline/configuration_generator.py
@@ -0,0 +1,64 @@
+# Copyright 2024, ASAM e.V.
+# This Source Code Form is subject to the terms of the Mozilla
+# Public License, v. 2.0. If a copy of the MPL was not distributed
+# with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+import sys, os, glob
+from lxml import etree
+
+XODR_TEMPLATE_PATH = "/app/demo_pipeline/templates/xodr_template.xml"
+XOSC_TEMPLATE_PATH = "/app/demo_pipeline/templates/xosc_template.xml"
+GENERATED_CONFIG_PATH = "/tmp/generated_config"
+
+
+def update_param_value(xml_file, name, new_value, output_file):
+ # Parse the XML file
+ tree = etree.parse(xml_file)
+ root = tree.getroot()
+
+ # Find the Param element with the name attribute and update its value attribute
+ for param in root.findall(f".//Param[@name='{name}']"):
+ param.set("value", new_value)
+
+ # Write the updated XML to the output file
+ tree.write(output_file, encoding="utf-8", pretty_print=True, xml_declaration=True)
+
+
+def main():
+ input_directory = "/input_directory"
+ input_filename = os.getenv("INPUT_FILENAME")
+
+ full_input_path = os.path.join(input_directory, input_filename)
+
+ os.makedirs(GENERATED_CONFIG_PATH, exist_ok=True)
+
+ if not os.path.isfile(full_input_path):
+ print("No file specified as input. Please provide xosc or xodr file. Exiting...")
+ return
+
+ print("Input file: ", full_input_path)
+ _, input_file_extension = os.path.splitext(full_input_path)
+
+ if input_file_extension == ".xosc":
+ print("XOSC selected")
+ update_param_value(
+ XOSC_TEMPLATE_PATH,
+ "XoscFile",
+ full_input_path,
+ os.path.join(GENERATED_CONFIG_PATH, "config.xml"),
+ )
+ elif input_file_extension == ".xodr":
+ print("XODR selected")
+ update_param_value(
+ XODR_TEMPLATE_PATH,
+ "XodrFile",
+ full_input_path,
+ os.path.join(GENERATED_CONFIG_PATH, "config.xml"),
+ )
+ else:
+ print(f"Error in input file extension. Unrecognized {input_file_extension}")
+ return
+
+
+if __name__ == "__main__":
+ main()
diff --git a/demo_pipeline/requirements.txt b/demo_pipeline/requirements.txt
new file mode 100644
index 00000000..dc26150e
--- /dev/null
+++ b/demo_pipeline/requirements.txt
@@ -0,0 +1 @@
+lxml==5.2.2
diff --git a/demo_pipeline/run_pipeline.sh b/demo_pipeline/run_pipeline.sh
new file mode 100755
index 00000000..09502612
--- /dev/null
+++ b/demo_pipeline/run_pipeline.sh
@@ -0,0 +1,16 @@
+# Copyright 2024, ASAM e.V.
+# This Source Code Form is subject to the terms of the Mozilla
+# Public License, v. 2.0. If a copy of the MPL was not distributed
+# with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+python3 /app/demo_pipeline/configuration_generator.py
+
+python3 /app/framework/runtime/runtime/runtime.py \
+ --config "/tmp/generated_config/config.xml" \
+ --install_dir "/app/framework/bin" \
+ --schema_dir "/app/framework/doc/schema"
+
+mkdir -p /out/qc-result-$INPUT_FILENAME
+cp /app/framework/bin/*.xqar /out/qc-result-$INPUT_FILENAME
+cp /app/framework/bin/*.txt /out/qc-result-$INPUT_FILENAME
+chown -R $USER_ID:$GROUP_ID /out/qc-result-$INPUT_FILENAME
diff --git a/demo_pipeline/templates/xodr_template.xml b/demo_pipeline/templates/xodr_template.xml
new file mode 100644
index 00000000..ea9e99f1
--- /dev/null
+++ b/demo_pipeline/templates/xodr_template.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo_pipeline/templates/xosc_template.xml b/demo_pipeline/templates/xosc_template.xml
new file mode 100644
index 00000000..1e953045
--- /dev/null
+++ b/demo_pipeline/templates/xosc_template.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo_pipeline/xodrBundle b/demo_pipeline/xodrBundle
new file mode 100644
index 00000000..8376b70f
--- /dev/null
+++ b/demo_pipeline/xodrBundle
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# Copyright 2024, ASAM e.V.
+# This Source Code Form is subject to the terms of the Mozilla
+# Public License, v. 2.0. If a copy of the MPL was not distributed
+# with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+readonly CONFIG_FILE=$1
+
+source /app/opendrive-venv/bin/activate
+cd /app/qc-opendrive
+python main.py -c $CONFIG_FILE
+cp *.xqar /app/framework/bin/
diff --git a/demo_pipeline/xoscBundle b/demo_pipeline/xoscBundle
new file mode 100644
index 00000000..44f896ea
--- /dev/null
+++ b/demo_pipeline/xoscBundle
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# Copyright 2024, ASAM e.V.
+# This Source Code Form is subject to the terms of the Mozilla
+# Public License, v. 2.0. If a copy of the MPL was not distributed
+# with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+readonly CONFIG_FILE=$1
+
+source /app/openscenario-venv/bin/activate
+cd /app/qc-openscenarioxml
+python main.py -c $CONFIG_FILE
+cp *.xqar /app/framework/bin/
diff --git a/doc/manual/cpp_base_library.md b/doc/manual/cpp_base_library.md
index 87c2df9a..b685b128 100644
--- a/doc/manual/cpp_base_library.md
+++ b/doc/manual/cpp_base_library.md
@@ -56,8 +56,8 @@ The results that a Checker or CheckerBundle defines as output are stored in a
report file. Reports contain information about the defects found, which are
called issues. At least a description and an identifier is assigned to an
issue. Additional meta information can be added to an issue: file location (
-cFileLocation ), XML file location ( cXMLLocation ) or road information (
-cRoadLocation ). This information is relevant for the ReportModule, for
+cFileLocation ), XML file location ( cXMLLocation ) or inertial location (
+cInertialLocation ). This information is relevant for the ReportModule, for
example, to point out meaningful errors in a GUI. The report XML file has to
follow the schema file doc/schema/xqar_report_format.xsd.
diff --git a/doc/manual/file_formats.md b/doc/manual/file_formats.md
index 8bd39b44..758d0609 100644
--- a/doc/manual/file_formats.md
+++ b/doc/manual/file_formats.md
@@ -64,13 +64,9 @@ or semantic flaws.
- **XmlLocation**
- Addressing in a XML file with help of a XPath expression
- Example: ``
- - **RoadLocation**
- - Position in road coordinates, the angles are calculated based on the
- road orientation
- - Example: ``
- **InertialLocation**
- Position in inertial coordinates
- - Example: ``
- Optional external files (e. g. Images of generated graphs such as speed
over distance). Currently not supported.
@@ -98,7 +94,7 @@ one called SyntaxChecker and one SemanticChecker.
-
+
diff --git a/doc/manual/viewer_interface.md b/doc/manual/viewer_interface.md
index 9bb0e744..ddc24b44 100644
--- a/doc/manual/viewer_interface.md
+++ b/doc/manual/viewer_interface.md
@@ -51,7 +51,7 @@ If you start a viewer the following functions are called in this order:
If an error occurs during the startup process, the ReportGUI will call
GetLastErrorMessage to print out the error in the ReportGUI itself.
-ShowIssue is triggered if you click on a RoadLocation issue in the ReportGUI.
+ShowIssue is triggered if you click on a InertialLocation issue in the ReportGUI.
It will send the clicked issue and its location to the viewer.
If the ReportGUI is closed a currently active Viewer receives the closeViewer
diff --git a/doc/schema/config_format.xsd b/doc/schema/config_format.xsd
index 90af61a5..286523ad 100644
--- a/doc/schema/config_format.xsd
+++ b/doc/schema/config_format.xsd
@@ -8,47 +8,49 @@ with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-->
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/schema/xqar_report_format.xsd b/doc/schema/xqar_report_format.xsd
index c4296f82..be5e484d 100644
--- a/doc/schema/xqar_report_format.xsd
+++ b/doc/schema/xqar_report_format.xsd
@@ -1,84 +1,119 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docker/Dockerfile.linux b/docker/Dockerfile.linux
index 9278ac52..cfd20556 100644
--- a/docker/Dockerfile.linux
+++ b/docker/Dockerfile.linux
@@ -8,7 +8,7 @@ FROM ubuntu:22.04 AS framework_builder
SHELL ["/bin/bash", "-c"]
RUN echo "Installing Dependencies..." && \
- apt update && apt install -y \
+ apt update && apt install -y \
g++ \
g++-10 \
make \
@@ -18,11 +18,15 @@ RUN echo "Installing Dependencies..." && \
qtbase5-dev \
libqt5xmlpatterns5-dev \
libxerces-c-dev \
- pkg-config && \
- echo "Dependencies installed."
+ pkg-config \
+ python3.10-venv \
+ git && \
+ echo "Dependencies installed."
RUN mkdir -p /app/framework
+WORKDIR /app
+
COPY examples /app/framework/examples
COPY include /app/framework/include
COPY scripts /app/framework/scripts
@@ -33,6 +37,7 @@ COPY CMakeLists.txt /app/framework/CMakeLists.txt
COPY version /app/framework/version
COPY licenses /app/framework/licenses
COPY runtime /app/framework/runtime
+COPY demo_pipeline /app/demo_pipeline
RUN echo "Building framework..." && \
cd /app/framework && \
@@ -46,37 +51,105 @@ RUN echo "Building framework..." && \
echo "Done."
+# Clone, configure venv, install by copying bash script to install dir
+RUN git clone --single-branch --branch develop https://github.com/asam-ev/qc-openscenarioxml.git && \
+ python3 -m venv openscenario-venv && \
+ source openscenario-venv/bin/activate && \
+ python3 -m pip install --no-cache-dir -r qc-openscenarioxml/requirements.txt && \
+ chmod +x /app/demo_pipeline/xoscBundle && \
+ cp /app/demo_pipeline/xoscBundle /home/root/qc-build/bin/xoscBundle && \
+ rm -rf /app/qc-openscenarioxml/.git
+
+# Clone, configure venv, install by copying bash script to install dir
+RUN git clone --single-branch --branch develop https://github.com/asam-ev/qc-opendrive.git && \
+ python3 -m venv opendrive-venv && \
+ source opendrive-venv/bin/activate && \
+ python3 -m pip install --no-cache-dir -r qc-opendrive/requirements.txt && \
+ chmod +x /app/demo_pipeline/xodrBundle && \
+ cp /app/demo_pipeline/xodrBundle /home/root/qc-build/bin/xodrBundle && \
+ rm -rf /app/qc-opendrive/.git
+
+# Create and setup demo and runtime virtual envs
+RUN python3 -m venv demo-pipeline-venv && \
+ source demo-pipeline-venv/bin/activate && \
+ python3 -m pip install --no-cache-dir -r /app/demo_pipeline/requirements.txt
+
+RUN python3 -m venv runtime-venv && \
+ source runtime-venv/bin/activate && \
+ python3 -m pip install --no-cache-dir -r /app/framework/runtime/requirements.txt
+
+
# Runtime stage
-FROM python:3.11.9-slim-bookworm as runtime_test
+FROM ubuntu:22.04 as runtime_test
+# Dependancies installation currently required by ResultPooling and TextReport modules
RUN echo "Installing Qt..." && \
- apt update && apt install -y \
+ apt update && apt install -y \
qtbase5-dev \
libqt5xmlpatterns5-dev \
libxerces-c-dev \
pkg-config && \
- echo "Dependencies installed."
+ echo "Dependencies installed."
RUN mkdir -p /app
-COPY runtime/requirements.txt /app/
-RUN pip install -r /app/requirements.txt
-
# For testing files
COPY --from=framework_builder /app/framework /app/framework
# Copy install directory in runtime image
-COPY --from=framework_builder /home/root/qc-build /app/framework/build
-
+COPY --from=framework_builder /home/root/qc-build/bin /app/framework/bin
+COPY --from=framework_builder /app/framework/build/test /app/framework/test
# @NOTE this is just because DemoCheckerBundle is not installed by default
-COPY --from=framework_builder /app/framework/build/examples/checker_bundle_example/DemoCheckerBundle /app/framework/build/bin/
-
-ENV PYTHONUNBUFFERED=1
+COPY --from=framework_builder /app/framework/build/examples/checker_bundle_example/DemoCheckerBundle /app/framework/bin/
+# Virtual envs
+COPY --from=framework_builder /app/runtime-venv /app/runtime-venv
WORKDIR /app/framework/runtime/
-CMD python3 -m pytest -rA > runtime_test.log && cp /app/framework/runtime/runtime_test.log /out/runtime_test.log
+SHELL ["/bin/bash", "-c"]
+
+CMD source /app/runtime-venv/bin/activate && python3 -m pytest -rA > runtime_test.log && cp /app/framework/runtime/runtime_test.log /out/runtime_test.log
# Runtime stage
FROM framework_builder as unit_test
-
CMD ctest --test-dir /app/framework/build -C Release && cp /app/framework/build/Testing/Temporary/LastTest.log /out/
+
+
+FROM ubuntu:22.04 as demo_pipeline
+
+LABEL org.opencontainers.image.source="https://github.com/asam-ev/qc-framework"
+LABEL org.opencontainers.image.description="QC Framework demo pipeline"
+LABEL org.opencontainers.image.licenses="MPL-2.0"
+
+# Dependencies installation currently required by ResultPooling and TextReport modules
+RUN apt update && apt install -y \
+ libqt5xmlpatterns5-dev \
+ libxerces-c-dev && \
+ rm -rf /var/lib/apt/lists/*
+
+RUN mkdir -p /app
+
+# Virtual envs
+COPY --from=framework_builder /app/runtime-venv /app/runtime-venv
+COPY --from=framework_builder /app/demo-pipeline-venv /app/demo-pipeline-venv
+COPY --from=framework_builder /app/opendrive-venv /app/opendrive-venv
+COPY --from=framework_builder /app/openscenario-venv /app/openscenario-venv
+
+# Framework components
+COPY --from=framework_builder /home/root/qc-build/bin /app/framework/bin
+COPY --from=framework_builder /app/demo_pipeline /app/demo_pipeline
+COPY --from=framework_builder /app/framework/runtime /app/framework/runtime
+
+# Framework schemas
+COPY --from=framework_builder /app/framework/doc/schema /app/framework/doc/schema
+
+# OpenScenario XML checker bundle
+COPY --from=framework_builder /app/qc-openscenarioxml/main.py /app/qc-openscenarioxml/main.py
+COPY --from=framework_builder /app/qc-openscenarioxml/qc_openscenario /app/qc-openscenarioxml/qc_openscenario
+
+# OpenDrive XML checker bundle
+COPY --from=framework_builder /app/qc-opendrive/main.py /app/qc-opendrive/main.py
+COPY --from=framework_builder /app/qc-opendrive/qc_opendrive /app/qc-opendrive/qc_opendrive
+
+SHELL ["/bin/bash", "-c"]
+
+CMD source /app/demo-pipeline-venv/bin/activate && /app/demo_pipeline/run_pipeline.sh
diff --git a/examples/checker_bundle_example/src/main.cpp b/examples/checker_bundle_example/src/main.cpp
index 988d4bf7..b5c9ce5d 100644
--- a/examples/checker_bundle_example/src/main.cpp
+++ b/examples/checker_bundle_example/src/main.cpp
@@ -10,12 +10,18 @@
#include "common/result_format/c_checker.h"
#include "common/result_format/c_checker_bundle.h"
+#include "common/result_format/c_domain_specific_info.h"
+#include "common/result_format/c_inertial_location.h"
+#include "common/result_format/c_locations_container.h"
#include "common/result_format/c_parameter_container.h"
#include "common/result_format/c_result_container.h"
+#include "common/result_format/c_rule.h"
#include "common/config_format/c_configuration.h"
#include "common/config_format/c_configuration_checker_bundle.h"
+#include
+#include
// Main Programm
int main(int argc, char *argv[])
{
@@ -112,6 +118,47 @@ void ShowHelp(const std::string &toolPath)
std::cout << "\n\n";
}
+DOMElement *getRootFromString(const std::string &inputStr)
+{
+ XMLPlatformUtils::Initialize();
+
+ XercesDOMParser *parser = new XercesDOMParser();
+ ErrorHandler *errHandler = (ErrorHandler *)new XERCES_CPP_NAMESPACE::HandlerBase();
+ parser->setErrorHandler(errHandler);
+
+ XERCES_CPP_NAMESPACE::MemBufInputSource memBufIS((const XMLByte *)inputStr.c_str(), inputStr.length(), "xmlBuffer",
+ false);
+
+ try
+ {
+ parser->parse(memBufIS);
+ }
+ catch (const XMLException &e)
+ {
+ char *message = XMLString::transcode(e.getMessage());
+ std::cerr << "XMLException: " << message << std::endl;
+ XMLString::release(&message);
+ return nullptr;
+ }
+ catch (const DOMException &e)
+ {
+ char *message = XMLString::transcode(e.msg);
+ std::cerr << "DOMException: " << message << std::endl;
+ XMLString::release(&message);
+ return nullptr;
+ }
+ catch (...)
+ {
+ std::cerr << "Unexpected exception" << std::endl;
+ return nullptr;
+ }
+
+ DOMDocument *doc = parser->getDocument();
+ DOMElement *rootElement = doc->getDocumentElement();
+
+ return rootElement;
+}
+
void RunChecks(const cParameterContainer &inputParams)
{
// Now we define a result container which contains our results.
@@ -125,10 +172,49 @@ void RunChecks(const cParameterContainer &inputParams)
// Create a checker with a factory in the checker bundle
cChecker *pExampeChecker = pExampleCheckerBundle->CreateChecker("exampleChecker", "This is a description");
-
// Lets add now an issue
pExampeChecker->AddIssue(new cIssue("This is an information from the demo usecase", INFO_LVL));
+ // Create a test checker with an inertial location
+ cChecker *pExampleInertialChecker =
+ pExampleCheckerBundle->CreateChecker("exampleInertialChecker", "This is a description of inertial checker");
+ std::list listLoc;
+ listLoc.push_back(new cLocationsContainer("inertial position", new cInertialLocation(1.0, 2.0, 3.0)));
+ pExampleInertialChecker->AddIssue(new cIssue("This is an information from the demo usecase", INFO_LVL, listLoc));
+
+ // Create a test checker with RuleUID and metadata
+ cChecker *pExampleRuleUIDChecker =
+ pExampleCheckerBundle->CreateChecker("exampleRuleUIDChecker", "This is a description of ruleUID checker");
+ pExampleRuleUIDChecker->AddRule(new cRule("test.com::qwerty.qwerty"));
+ pExampleRuleUIDChecker->AddMetadata(
+ new cMetadata("run date", "2024/06/06", "Date in which the checker was executed"));
+ pExampleRuleUIDChecker->AddMetadata(
+ new cMetadata("reference project", "project01", "Name of the project that created the checker"));
+
+ // Create a test checker with Issue and RuleUID
+ cChecker *pExampleIssueRuleChecker = pExampleCheckerBundle->CreateChecker(
+ "exampleIssueRuleChecker", "This is a description of checker with issue and the involved ruleUID");
+
+ pExampleIssueRuleChecker->AddIssue(
+ new cIssue("This is an information from the demo usecase", ERROR_LVL, "test.com::qwerty.qwerty"));
+
+ // Create a test checker with Issue and RuleUID
+ cChecker *pSkippedChecker = pExampleCheckerBundle->CreateChecker(
+ "exampleSkippedChecker", "This is a description of checker with skipped status", "Skipped execution",
+ "skipped");
+
+ // Create a test checker with an inertial location
+ cChecker *pExampleDomainChecker = pExampleCheckerBundle->CreateChecker(
+ "exampleDomainChecker", "This is a description of example domain info checker");
+ std::list listDomainSpecificInfo;
+
+ std::string xmlString =
+ "";
+
+ listDomainSpecificInfo.push_back(new cDomainSpecificInfo(getRootFromString(xmlString), "domain info test"));
+ pExampleDomainChecker->AddIssue(
+ new cIssue("This is an information from the demo usecase", INFO_LVL, listDomainSpecificInfo));
+
// Lets add a summary for the checker bundle
unsigned int issueCount = pExampleCheckerBundle->GetIssueCount();
std::stringstream ssSummaryString;
diff --git a/include/common/result_format/c_checker.h b/include/common/result_format/c_checker.h
index f45f7527..23ecf356 100644
--- a/include/common/result_format/c_checker.h
+++ b/include/common/result_format/c_checker.h
@@ -12,7 +12,9 @@
#include "../util.h"
#include "../xml/util_xerces.h"
#include "c_issue.h"
+#include "c_metadata.h"
#include "c_parameter_container.h"
+#include "c_rule.h"
#include
#include
@@ -20,6 +22,8 @@
// Forward declaration to avoid problems with circular dependencies (especially under Linux)
class cCheckerBundle;
class cIssue;
+class cRule;
+class cMetadata;
/*
* Definition of a basic checker
@@ -28,12 +32,15 @@ class cChecker
{
friend class cCheckerBundle;
friend class cIssue;
+ friend class cRule;
+ friend class cMetadata;
public:
static const XMLCh *TAG_CHECKER;
static const XMLCh *ATTR_CHECKER_ID;
static const XMLCh *ATTR_DESCRIPTION;
static const XMLCh *ATTR_SUMMARY;
+ static const XMLCh *ATTR_STATUS;
// Returns the checker id
std::string GetCheckerID() const;
@@ -41,6 +48,9 @@ class cChecker
// Returns the summary
std::string GetSummary() const;
+ // Returns the status
+ std::string GetStatus() const;
+
// Returns the description
std::string GetDescription() const;
@@ -50,12 +60,27 @@ class cChecker
// sets the summary
void SetSummary(const std::string &strSummary);
+ // sets the status
+ void SetStatus(const std::string &eStatus);
+
/*
* Adds an issue to the checker results
* \param instance if the result
*/
cIssue *AddIssue(cIssue *const issueToAdd);
+ /*
+ * Adds an rule to the checker results
+ * \param instance if the result
+ */
+ cRule *AddRule(cRule *const ruleToAdd);
+
+ /*
+ * Adds an metadata info to the checker results
+ * \param instance if the result
+ */
+ cMetadata *AddMetadata(cMetadata *const metadataToAdd);
+
// Clears all issues from the container
void Clear();
@@ -71,12 +96,24 @@ class cChecker
// Counts the Issues
unsigned int GetIssueCount();
+ // Counts the Rules
+ unsigned int GetRuleCount();
+
+ // Counts the Rules
+ unsigned int GetMetadataCount();
+
// Updates the summary
void UpdateSummary();
// Returns the issues
std::list GetIssues();
+ // Returns the rules
+ std::list GetRules();
+
+ // Returns the rules
+ std::list GetMetadata();
+
// Processes every issue and does a defined processing
void DoProcessing(void (*funcIzteratorPtr)(cIssue *));
@@ -149,13 +186,15 @@ class cChecker
protected:
// Creates a new checker instance
- cChecker(const std::string &strCheckerId, const std::string &strDescription, const std::string &strSummary)
- : m_Bundle(nullptr), m_CheckerId(strCheckerId), m_Description(strDescription), m_Summary(strSummary)
+ cChecker(const std::string &strCheckerId, const std::string &strDescription, const std::string &strSummary,
+ const std::string &strStatus)
+ : m_Bundle(nullptr), m_CheckerId(strCheckerId), m_Description(strDescription), m_Summary(strSummary),
+ m_Status(strStatus)
{
}
// Creates a new checker instance
- cChecker() : m_Bundle(nullptr), m_CheckerId(""), m_Description(""), m_Summary("")
+ cChecker() : m_Bundle(nullptr), m_CheckerId(""), m_Description(""), m_Summary(""), m_Status("completed")
{
}
@@ -170,9 +209,12 @@ class cChecker
std::string m_CheckerId;
std::string m_Description;
std::string m_Summary;
+ std::string m_Status;
cCheckerBundle *m_Bundle;
std::list m_Issues;
+ std::list m_Rules;
+ std::list m_Metadata;
cParameterContainer m_Params;
};
diff --git a/include/common/result_format/c_checker_bundle.h b/include/common/result_format/c_checker_bundle.h
index e6b3d525..12964b4c 100644
--- a/include/common/result_format/c_checker_bundle.h
+++ b/include/common/result_format/c_checker_bundle.h
@@ -12,6 +12,7 @@
#include "../util.h"
#include "../xml/util_xerces.h"
#include "c_parameter_container.h"
+#include "common/result_format/c_checker.h"
#include "common/result_format/c_issue.h"
// Forward declaration to avoid problems with circular dependencies (especially under Linux)
@@ -56,7 +57,7 @@ class cCheckerBundle
// Adds a new checker
cChecker *CreateChecker(const std::string &checkerId, const std::string &strDescription = "",
- const std::string &strSummary = "");
+ const std::string &strSummary = "", const std::string &strStatus = "completed");
/*
* Adds an amout of issues to the checker bundle
diff --git a/include/common/result_format/c_domain_specific_info.h b/include/common/result_format/c_domain_specific_info.h
new file mode 100644
index 00000000..3963b9cd
--- /dev/null
+++ b/include/common/result_format/c_domain_specific_info.h
@@ -0,0 +1,67 @@
+/**
+ * Copyright 2024, ASAM e.V.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla
+ * Public License, v. 2.0. If a copy of the MPL was not distributed
+ * with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef cDomainSpecificInfo_h__
+#define cDomainSpecificInfo_h__
+
+#include "../xml/util_xerces.h"
+#include "string"
+#include
+
+XERCES_CPP_NAMESPACE_USE
+
+/*
+ * Definition of domain specific information. This can be used to represent custom info in result file
+ */
+class cDomainSpecificInfo
+{
+
+ public:
+ static const XMLCh *TAG_DOMAIN_SPECIFIC_INFO;
+ static const XMLCh *ATTR_NAME;
+ /*
+ * Creates a new instance of cDomainSpecificInfo
+ * \param inputRoot: xml tree root for the initialization
+ * \param name: Name of the tag
+ */
+ cDomainSpecificInfo(DOMElement *inputRoot, const std::string &name = "") : m_Name(name)
+ {
+ // Get the original document's implementation
+ DOMImplementation *impl = inputRoot->getOwnerDocument()->getImplementation();
+ // Create a new document to own the cloned element
+ m_Doc = impl->createDocument();
+ // Import the element into the new document, effectively cloning it
+ m_Root = dynamic_cast(m_Doc->importNode(inputRoot, true));
+ }
+
+ // Serialize this information
+ virtual XERCES_CPP_NAMESPACE::DOMElement *WriteXML(XERCES_CPP_NAMESPACE::DOMDocument *p_resultDocument);
+
+ // Unserialize this information
+ static cDomainSpecificInfo *ParseFromXML(XERCES_CPP_NAMESPACE::DOMNode *pXMLNode,
+ XERCES_CPP_NAMESPACE::DOMElement *pXMLElement);
+
+ // Returns the root
+ DOMElement *GetRoot() const;
+ // Returns the name
+ std::string GetName() const;
+ DOMDocument *GetDoc() const;
+
+ ~cDomainSpecificInfo();
+
+ protected:
+ DOMElement *m_Root;
+ DOMDocument *m_Doc;
+ std::string m_Name;
+
+ private:
+ cDomainSpecificInfo();
+ cDomainSpecificInfo(const cDomainSpecificInfo &);
+};
+
+#endif
diff --git a/include/common/result_format/c_inertial_location.h b/include/common/result_format/c_inertial_location.h
index ebde1348..c0230b87 100644
--- a/include/common/result_format/c_inertial_location.h
+++ b/include/common/result_format/c_inertial_location.h
@@ -24,9 +24,6 @@ class cInertialLocation : public cExtendedInformation
static const XMLCh *ATTR_X;
static const XMLCh *ATTR_Y;
static const XMLCh *ATTR_Z;
- static const XMLCh *ATTR_H;
- static const XMLCh *ATTR_P;
- static const XMLCh *ATTR_R;
/*
* Creates a new instance of cInertialLocation
@@ -36,19 +33,7 @@ class cInertialLocation : public cExtendedInformation
* \param description: Additional description
*/
cInertialLocation(double x, double y, double z)
- : cExtendedInformation("InertialLocation"), m_X(x), m_Y(y), m_Z(z), m_H(0.0), m_P(0.0), m_R(0.0)
- {
- }
-
- /*
- * Creates a new instance of cInertialLocation
- * \param x: X of the position in inertial coordinate system
- * \param y: Y of the position in inertial coordinate system
- * \param z: Z of the position in inertial coordinate system
- * \param description: Additional description
- */
- cInertialLocation(double x, double y, double z, double head, double pitch, double roll)
- : cExtendedInformation("InertialLocation"), m_X(x), m_Y(y), m_Z(z), m_H(head), m_P(pitch), m_R(roll)
+ : cExtendedInformation("InertialLocation"), m_X(x), m_Y(y), m_Z(z)
{
}
@@ -68,18 +53,10 @@ class cInertialLocation : public cExtendedInformation
// Returns the Z
double GetZ() const;
- // Returns the Head
- double GetHead() const;
-
- // Returns the Pitch
- double GetPitch() const;
-
- // Returns the Roll
- double GetRoll() const;
+
protected:
double m_X, m_Y, m_Z;
- double m_H, m_P, m_R;
private:
cInertialLocation();
diff --git a/include/common/result_format/c_issue.h b/include/common/result_format/c_issue.h
index 2bd744ec..5299ee32 100644
--- a/include/common/result_format/c_issue.h
+++ b/include/common/result_format/c_issue.h
@@ -19,6 +19,7 @@
class cChecker;
class cLocationsContainer;
+class cDomainSpecificInfo;
/*
* Definition of issue levels
@@ -42,6 +43,7 @@ class cIssue : public IResult
static const XMLCh *ATTR_ISSUE_ID;
static const XMLCh *ATTR_DESCRIPTION;
static const XMLCh *ATTR_LEVEL;
+ static const XMLCh *ATTR_RULEUID;
static const std::map issueLevelToString;
@@ -49,7 +51,8 @@ class cIssue : public IResult
* Creates a new Issue
*
*/
- cIssue(const std::string &description, eIssueLevel infoLvl, cLocationsContainer *locationsContainer = nullptr);
+ cIssue(const std::string &description, eIssueLevel infoLvl, const std::string &ruleUID = "",
+ cLocationsContainer *locationsContainer = nullptr, cDomainSpecificInfo *domainSpecificInfo = nullptr);
/*
* Creates a new Issue
@@ -57,14 +60,26 @@ class cIssue : public IResult
*/
cIssue(const std::string &description, eIssueLevel infoLvl, std::list listLoc);
+ cIssue(const std::string &description, eIssueLevel infoLvl,
+ std::list listDomainSpecificInfo);
+
+ cIssue(const std::string &description, eIssueLevel infoLvl, const std::string &ruleUID,
+ std::list listLoc);
+
~cIssue();
// Adds extendesd information to this issue
void AddLocationsContainer(cLocationsContainer *locationsContainer);
+ // Adds domain specific info to this issue
+ void AddDomainSpecificInfo(cDomainSpecificInfo *domainSpecificInfo);
+
// Adds extendesd information to this issue
void AddLocationsContainer(std::list listLoc);
+ // Adds domain specific info to this issue
+ void AddDomainSpecificInfo(std::list listDomainSpecificInfo);
+
// Write the xml for this issue
virtual DOMElement *WriteXML(XERCES_CPP_NAMESPACE::DOMDocument *p_resultDocument);
@@ -74,6 +89,8 @@ class cIssue : public IResult
// Returns th count of locations
std::size_t GetLocationsCount() const;
+ size_t GetDomainSpecificCount() const;
+
// Assigns an issue to a checker
void AssignChecker(cChecker *checkerToAssign);
@@ -95,9 +112,15 @@ class cIssue : public IResult
// Sets the level
void SetLevel(eIssueLevel level);
+ // Sets the RuleUID
+ void SetRuleUID(const std::string &strRuleUID);
+
// Returns the description
std::string GetDescription() const;
+ // Returns the ruleUID
+ std::string GetRuleUID() const;
+
// Returns the issue level
eIssueLevel GetIssueLevel() const;
@@ -110,9 +133,14 @@ class cIssue : public IResult
// Returns true if this issue has location containers
bool HasLocations() const;
+ bool HasDomainSpecificInfo() const;
+
// Returns all extended informations
std::list GetLocationsContainer() const;
+ // Returns all domain specific info
+ std::list GetDomainSpecificInfo() const;
+
// Returns the checker this issue belongs to
cChecker *GetChecker() const;
@@ -129,9 +157,11 @@ class cIssue : public IResult
unsigned long long m_Id;
std::string m_Description;
eIssueLevel m_IssueLevel;
+ std::string m_RuleUID;
cChecker *m_Checker;
std::list m_Locations;
+ std::list m_DomainSpecificInfo;
};
std::string PrintIssueLevel(const eIssueLevel);
diff --git a/include/common/result_format/c_metadata.h b/include/common/result_format/c_metadata.h
new file mode 100644
index 00000000..f44baaf3
--- /dev/null
+++ b/include/common/result_format/c_metadata.h
@@ -0,0 +1,64 @@
+/**
+ * Copyright 2024, ASAM e.V.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla
+ * Public License, v. 2.0. If a copy of the MPL was not distributed
+ * with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef cMetadata_h__
+#define cMetadata_h__
+
+#include "../xml/util_xerces.h"
+#include "string"
+
+class cChecker;
+
+class cMetadata
+{
+
+ public:
+ static const XMLCh *TAG_NAME;
+ static const XMLCh *ATTR_KEY;
+ static const XMLCh *ATTR_VALUE;
+ static const XMLCh *ATTR_DESCRIPTION;
+
+ /*
+ * Creates a new instance of cMetadata
+ * \param m_Key: metadata key
+ * \param m_Value: metadata value
+ * \param m_Description: metadata description
+ * \param description: Additional description
+ */
+ cMetadata(const std::string &input_key, const std::string &input_value, const std::string &input_description)
+ : m_Key(input_key), m_Value(input_value), m_Description(input_description)
+ {
+ }
+
+ // Serialize this information
+ virtual XERCES_CPP_NAMESPACE::DOMElement *WriteXML(XERCES_CPP_NAMESPACE::DOMDocument *p_resultDocument);
+
+ // Unserialize this information
+ static cMetadata *ParseFromXML(XERCES_CPP_NAMESPACE::DOMNode *pXMLNode,
+ XERCES_CPP_NAMESPACE::DOMElement *pXMLElement, cChecker *checker);
+
+ // Assigns an issue to a checker
+ void AssignChecker(cChecker *checkerToAssign);
+
+ // Returns the Key
+ std::string GetKey() const;
+ // Returns the Value
+ std::string GetValue() const;
+ // Returns the Description
+ std::string GetDescription() const;
+
+ protected:
+ std::string m_Key, m_Value, m_Description;
+ cChecker *m_Checker;
+
+ private:
+ cMetadata();
+ cMetadata(const cMetadata &);
+};
+
+#endif
diff --git a/include/common/result_format/c_road_location.h b/include/common/result_format/c_road_location.h
deleted file mode 100644
index ca5dcceb..00000000
--- a/include/common/result_format/c_road_location.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Copyright 2023 CARIAD SE.
- *
- * This Source Code Form is subject to the terms of the Mozilla
- * Public License, v. 2.0. If a copy of the MPL was not distributed
- * with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-#ifndef cRoadLocation_h__
-#define cRoadLocation_h__
-
-#include "../xml/util_xerces.h"
-#include "c_extended_information.h"
-
-/*
- * Definition of additional road location. This can be used to debug special positions
- * in dbqa framework.
- */
-class cRoadLocation : public cExtendedInformation
-{
-
- public:
- static const XMLCh *TAG_NAME;
- static const XMLCh *ATTR_ROAD_ID;
- static const XMLCh *ATTR_S;
- static const XMLCh *ATTR_T;
-
- /*
- * Creates a new instance of cRoadLocation
- * \param roadId: ID of the road in OpenDrive
- * \param s: S of the road in OpenDrive
- * \param t: T of the road in OpenDrive
- */
- cRoadLocation(const std::string &roadId, float s = 0.0f, float t = 0.0f) : cExtendedInformation("RoadLocation")
- {
- m_RoadID = roadId;
- m_S = s;
- m_T = t;
- }
-
- // Serialize this information
- virtual XERCES_CPP_NAMESPACE::DOMElement *WriteXML(XERCES_CPP_NAMESPACE::DOMDocument *p_resultDocument);
-
- // Unserialize this information
- static cRoadLocation *ParseFromXML(XERCES_CPP_NAMESPACE::DOMNode *pXMLNode,
- XERCES_CPP_NAMESPACE::DOMElement *pXMLElement);
-
- // Returns the xPath
- std::string GetRoadID() const;
-
- // Returns the road Id as integer
- void GetRoadID(int &roadId) const;
-
- // Returns the s of the road
- float GetS() const;
-
- // Returns the t of the road
- float GetT() const;
-
- protected:
- std::string m_RoadID;
- float m_S;
- float m_T;
-
- private:
- cRoadLocation();
- cRoadLocation(const cRoadLocation &);
-};
-
-#endif
diff --git a/include/common/result_format/c_rule.h b/include/common/result_format/c_rule.h
new file mode 100644
index 00000000..2e3bf79d
--- /dev/null
+++ b/include/common/result_format/c_rule.h
@@ -0,0 +1,58 @@
+/**
+ * Copyright 2024, ASAM e.V.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla
+ * Public License, v. 2.0. If a copy of the MPL was not distributed
+ * with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef cRule_h__
+#define cRule_h__
+
+#include "../xml/util_xerces.h"
+#include "string"
+
+class cChecker;
+/*
+ * Definition of additional interial location information. This can be used to debug special positions
+ * in dbqa framework
+ */
+class cRule
+{
+
+ public:
+ static const XMLCh *TAG_NAME;
+ static const XMLCh *ATTR_RULE_UID;
+
+ /*
+ * Creates a new instance of cRule
+ * \param m_RuleUID: rule id
+ * \param description: Additional description
+ */
+ cRule(const std::string &input_string) : m_RuleUID(input_string)
+ {
+ }
+
+ // Serialize this information
+ virtual XERCES_CPP_NAMESPACE::DOMElement *WriteXML(XERCES_CPP_NAMESPACE::DOMDocument *p_resultDocument);
+
+ // Unserialize this information
+ static cRule *ParseFromXML(XERCES_CPP_NAMESPACE::DOMNode *pXMLNode, XERCES_CPP_NAMESPACE::DOMElement *pXMLElement,
+ cChecker *checker);
+
+ // Assigns an issue to a checker
+ void AssignChecker(cChecker *checkerToAssign);
+
+ // Returns the X
+ std::string GetRuleUID() const;
+
+ protected:
+ std::string m_RuleUID;
+ cChecker *m_Checker;
+
+ private:
+ cRule();
+ cRule(const cRule &);
+};
+
+#endif
diff --git a/runtime/tests/test_data/3steps_config.xml b/runtime/tests/test_data/3steps_config.xml
new file mode 100644
index 00000000..74c0f058
--- /dev/null
+++ b/runtime/tests/test_data/3steps_config.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/runtime/tests/test_runtime.py b/runtime/tests/test_runtime.py
index 7b909fc8..80a68a8a 100644
--- a/runtime/tests/test_runtime.py
+++ b/runtime/tests/test_runtime.py
@@ -57,15 +57,16 @@ def check_node_exists(xml_file: str, node_name: str) -> bool:
def test_runtime_execution():
- install_dir = os.path.join("..", "build", "bin")
+ start_wd = os.getcwd()
+ install_dir = os.path.join("..", "bin")
os.chdir(install_dir)
config_xml = os.path.join(
- "..", "..", "runtime", "tests", "test_data", "DemoCheckerBundle_config.xml"
+ "..", "runtime", "tests", "test_data", "DemoCheckerBundle_config.xml"
)
- schema_dir = os.path.join("..", "..", "doc", "schema")
- runtime_script = os.path.join("..", "..", "runtime", "runtime", "runtime.py")
+ schema_dir = os.path.join("..", "doc", "schema")
+ runtime_script = os.path.join("..", "runtime", "runtime", "runtime.py")
process = subprocess.Popen(
f"python3 {runtime_script} --config={config_xml} --install_dir={os.getcwd()} --schema_dir={schema_dir}",
@@ -93,3 +94,43 @@ def test_runtime_execution():
# Check that at least one node called "Issue" is present in the result
node_name = "Issue"
assert check_node_exists(result_file, node_name)
+
+ os.chdir(start_wd)
+
+
+def test_3steps_config():
+
+ start_wd = os.getcwd()
+ install_dir = os.path.join("..", "bin")
+ os.chdir(install_dir)
+
+ config_xml = os.path.join("..", "runtime", "tests", "test_data", "3steps_config.xml")
+
+ schema_dir = os.path.join("..", "doc", "schema")
+ runtime_script = os.path.join("..", "runtime", "runtime", "runtime.py")
+
+ process = subprocess.Popen(
+ f"python3 {runtime_script} --config={config_xml} --install_dir={os.getcwd()} --schema_dir={schema_dir}",
+ shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd=os.getcwd(),
+ )
+ stdout, stderr = process.communicate()
+ exit_code = process.returncode
+ if exit_code == 0:
+ print("Command executed successfully.")
+ print("Output:")
+ print(stdout.decode())
+ else:
+ print("Error occurred while executing the command.")
+ print("Error message:")
+ print(stderr.decode())
+ # Check that result file is correctly generated
+ result_file = os.path.join("Result.xqar")
+ assert os.path.isfile(result_file)
+ # Check that report txt file is correctly generated
+ result_file = os.path.join("Report.txt")
+ assert os.path.isfile(result_file)
+
+ os.chdir(start_wd)
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 7f0f2589..9cfe7b49 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -21,7 +21,6 @@ add_library(qc4openx-common STATIC
src/result_format/c_extended_information.cpp
src/result_format/c_file_location.cpp
src/result_format/c_inertial_location.cpp
- src/result_format/c_road_location.cpp
src/result_format/c_xml_location.cpp
src/result_format/c_parameter_container.cpp
src/result_format/c_locations_container.cpp
@@ -30,6 +29,9 @@ add_library(qc4openx-common STATIC
src/config_format/c_configuration_checker_bundle.cpp
src/config_format/c_configuration_report_module.cpp
src/xml/c_x_path_evaluator.cpp
+ src/result_format/c_rule.cpp
+ src/result_format/c_metadata.cpp
+ src/result_format/c_domain_specific_info.cpp
)
target_include_directories(qc4openx-common PUBLIC ${PROJECT_SOURCE_DIR}/include
diff --git a/src/common/src/config_format/c_configuration.cpp b/src/common/src/config_format/c_configuration.cpp
index 55d86fd0..6b2d9222 100644
--- a/src/common/src/config_format/c_configuration.cpp
+++ b/src/common/src/config_format/c_configuration.cpp
@@ -21,7 +21,6 @@ cConfiguration::~cConfiguration()
bool cConfiguration::ParseFromXML(cConfiguration *config, const std::string &configFilePath)
{
- XMLPlatformUtils::Initialize();
if (!CheckIfFileExists(configFilePath))
return false;
@@ -70,9 +69,6 @@ bool cConfiguration::ParseFromXML(cConfiguration *config, const std::string &con
}
delete pDomParser;
-
- XMLPlatformUtils::Terminate();
-
return true;
}
@@ -88,7 +84,6 @@ cConfiguration *cConfiguration::ParseFromXML(const std::string &configFilePath)
void cConfiguration::WriteConfigurationToFile(const std::string &filePath)
{
- XMLPlatformUtils::Initialize();
DOMImplementation *p_DOMImplementationCore =
DOMImplementationRegistry::getDOMImplementation(XMLString::transcode("core"));
DOMLSSerializer *p_DOMSerializer = ((DOMImplementationLS *)p_DOMImplementationCore)->createLSSerializer();
@@ -130,8 +125,6 @@ void cConfiguration::WriteConfigurationToFile(const std::string &filePath)
p_resultDocument->release();
theOutput->release();
p_DOMSerializer->release();
-
- XMLPlatformUtils::Terminate();
}
void cConfiguration::ProcessDomNode(DOMNode *const nodeToProcess, cConfiguration *const cConfig) const
diff --git a/src/common/src/result_format/c_checker.cpp b/src/common/src/result_format/c_checker.cpp
index bc00bc3e..03e510c2 100644
--- a/src/common/src/result_format/c_checker.cpp
+++ b/src/common/src/result_format/c_checker.cpp
@@ -12,6 +12,7 @@ const XMLCh *cChecker::TAG_CHECKER = CONST_XMLCH("Checker");
const XMLCh *cChecker::ATTR_CHECKER_ID = CONST_XMLCH("checkerId");
const XMLCh *cChecker::ATTR_DESCRIPTION = CONST_XMLCH("description");
const XMLCh *cChecker::ATTR_SUMMARY = CONST_XMLCH("summary");
+const XMLCh *cChecker::ATTR_STATUS = CONST_XMLCH("status");
XERCES_CPP_NAMESPACE_USE
@@ -33,6 +34,12 @@ std::string cChecker::GetSummary() const
return m_Summary;
}
+// Returns the status
+std::string cChecker::GetStatus() const
+{
+ return m_Status;
+}
+
// Returns the description
std::string cChecker::GetDescription() const
{
@@ -45,6 +52,12 @@ void cChecker::SetDescription(const std::string &strDescription)
m_Description = strDescription;
}
+// Sets the description
+void cChecker::SetStatus(const std::string &eStatus)
+{
+ m_Status = eStatus;
+}
+
// Write the xml for this issue
DOMElement *cChecker::WriteXML(DOMDocument *pResultDocument)
{
@@ -63,6 +76,24 @@ DOMElement *cChecker::WriteXML(DOMDocument *pResultDocument)
pCheckerNode->appendChild(p_DataElement);
}
+ // Add Rules und cCheckerSummaries
+ for (std::list::const_iterator it = m_Rules.begin(); it != m_Rules.end(); ++it)
+ {
+ DOMElement *p_DataElement = (*it)->WriteXML(pResultDocument);
+
+ if (nullptr != p_DataElement)
+ pCheckerNode->appendChild(p_DataElement);
+ }
+
+ // Add Metadatas und cCheckerSummaries
+ for (std::list::const_iterator it = m_Metadata.begin(); it != m_Metadata.end(); ++it)
+ {
+ DOMElement *p_DataElement = (*it)->WriteXML(pResultDocument);
+
+ if (nullptr != p_DataElement)
+ pCheckerNode->appendChild(p_DataElement);
+ }
+
return pCheckerNode;
}
@@ -77,9 +108,9 @@ cChecker *cChecker::ParseFromXML(DOMNode *pXMLNode, DOMElement *pXMLElement, cCh
std::string strCheckerId = XMLString::transcode(pXMLElement->getAttribute(ATTR_CHECKER_ID));
std::string strSummary = XMLString::transcode(pXMLElement->getAttribute(ATTR_SUMMARY));
std::string strDescription = XMLString::transcode(pXMLElement->getAttribute(ATTR_DESCRIPTION));
+ std::string strStatus = XMLString::transcode(pXMLElement->getAttribute(ATTR_STATUS));
- cChecker *pChecker = new cChecker(strCheckerId, strDescription, strSummary);
-
+ cChecker *pChecker = new cChecker(strCheckerId, strDescription, strSummary, strStatus);
pChecker->AssignCheckerBundle(checkerBundle);
DOMNodeList *pIssueChildList = pXMLNode->getChildNodes();
@@ -123,14 +154,17 @@ DOMElement *cChecker::CreateNode(DOMDocument *pDOMDocResultDocument)
XMLCh *pCheckerId = XMLString::transcode(m_CheckerId.c_str());
XMLCh *pDescription = XMLString::transcode(m_Description.c_str());
XMLCh *pSummary = XMLString::transcode(m_Summary.c_str());
+ XMLCh *pStatus = XMLString::transcode(m_Status.c_str());
pBundleSummary->setAttribute(ATTR_CHECKER_ID, pCheckerId);
pBundleSummary->setAttribute(ATTR_DESCRIPTION, pDescription);
pBundleSummary->setAttribute(ATTR_SUMMARY, pSummary);
+ pBundleSummary->setAttribute(ATTR_STATUS, pStatus);
XMLString::release(&pCheckerId);
XMLString::release(&pDescription);
XMLString::release(&pSummary);
+ XMLString::release(&pStatus);
return pBundleSummary;
}
@@ -168,6 +202,49 @@ cIssue *cChecker::AddIssue(cIssue *const issueToAdd)
return nullptr;
}
+cRule *cChecker::AddRule(cRule *const ruleToAdd)
+{
+ if (nullptr == m_Bundle)
+ {
+ // use runtime_error instead of exception for linux
+ throw std::runtime_error("Create the checker by using CheckerBundle::CreateChecker()!");
+ }
+ else
+ {
+ ruleToAdd->AssignChecker(this);
+ m_Rules.push_back(ruleToAdd);
+
+ return ruleToAdd;
+ }
+ return nullptr;
+}
+
+cMetadata *cChecker::AddMetadata(cMetadata *const metadataToAdd)
+{
+ if (nullptr == m_Bundle)
+ {
+ // use runtime_error instead of exception for linux
+ throw std::runtime_error("Create the checker by using CheckerBundle::CreateChecker()!");
+ }
+ else
+ {
+ metadataToAdd->AssignChecker(this);
+ m_Metadata.push_back(metadataToAdd);
+
+ return metadataToAdd;
+ }
+ return nullptr;
+}
+
+unsigned int cChecker::GetRuleCount()
+{
+ return (unsigned int)m_Rules.size();
+}
+
+unsigned int cChecker::GetMetadataCount()
+{
+ return (unsigned int)m_Metadata.size();
+}
// Deletes all issues
void cChecker::Clear()
{
@@ -175,6 +252,16 @@ void cChecker::Clear()
delete *it;
m_Issues.clear();
+
+ for (std::list::iterator it = m_Rules.begin(); it != m_Rules.end(); it++)
+ delete *it;
+
+ m_Rules.clear();
+
+ for (std::list::iterator it = m_Metadata.begin(); it != m_Metadata.end(); it++)
+ delete *it;
+
+ m_Metadata.clear();
}
// Counts the Issues
@@ -189,6 +276,16 @@ std::list cChecker::GetIssues()
return m_Issues;
}
+std::list cChecker::GetRules()
+{
+ return m_Rules;
+}
+
+std::list cChecker::GetMetadata()
+{
+ return m_Metadata;
+}
+
// Assigns a specific bundle to the checker
void cChecker::AssignCheckerBundle(cCheckerBundle *myBundle)
{
diff --git a/src/common/src/result_format/c_checker_bundle.cpp b/src/common/src/result_format/c_checker_bundle.cpp
index 04a11881..ffb7a4f4 100644
--- a/src/common/src/result_format/c_checker_bundle.cpp
+++ b/src/common/src/result_format/c_checker_bundle.cpp
@@ -147,15 +147,15 @@ cChecker *cCheckerBundle::CreateChecker(cChecker *newChecker)
// Adds a new checker
cChecker *cCheckerBundle::CreateChecker(const std::string &checkerId, const std::string &strDescription,
- const std::string &strSummary)
+ const std::string &strSummary, const std::string &strStatus)
{
- return CreateChecker(new cChecker(checkerId, strDescription, strSummary));
+ return CreateChecker(new cChecker(checkerId, strDescription, strSummary, strStatus));
}
cChecker *cCheckerBundle::CreateCheckerWithIssues(const std::string &strCheckerId, const std::string &strDescription,
eIssueLevel issueLevel, std::map m_Issues)
{
- cChecker *pChecker = new cChecker(strCheckerId, strDescription, "");
+ cChecker *pChecker = new cChecker(strCheckerId, strDescription, "", "completed");
CreateChecker(pChecker);
for (std::map::const_iterator it = m_Issues.cbegin(); it != m_Issues.cend(); it++)
diff --git a/src/common/src/result_format/c_domain_specific_info.cpp b/src/common/src/result_format/c_domain_specific_info.cpp
new file mode 100644
index 00000000..ac34e38d
--- /dev/null
+++ b/src/common/src/result_format/c_domain_specific_info.cpp
@@ -0,0 +1,62 @@
+/**
+ * Copyright 2024, ASAM e.V.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla
+ * Public License, v. 2.0. If a copy of the MPL was not distributed
+ * with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+#include "common/result_format/c_domain_specific_info.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+const XMLCh *cDomainSpecificInfo::TAG_DOMAIN_SPECIFIC_INFO = CONST_XMLCH("DomainSpecificInfo");
+const XMLCh *cDomainSpecificInfo::ATTR_NAME = CONST_XMLCH("name");
+// Returns the root
+DOMElement *cDomainSpecificInfo::GetRoot() const
+{
+ return m_Root;
+}
+DOMDocument *cDomainSpecificInfo::GetDoc() const
+{
+ return m_Doc;
+}
+std::string cDomainSpecificInfo::GetName() const
+{
+ return m_Name;
+}
+
+cDomainSpecificInfo::~cDomainSpecificInfo()
+{
+ m_Doc->release();
+}
+
+DOMElement *cDomainSpecificInfo::WriteXML(DOMDocument *p_resultDocument)
+{
+ DOMElement *p_DataElement = p_resultDocument->createElement(TAG_DOMAIN_SPECIFIC_INFO);
+ XMLCh *pName = XMLString::transcode(m_Name.c_str());
+ p_DataElement->setAttribute(ATTR_NAME, pName);
+
+ // Import the root element from the original document to the new document
+ DOMElement *importedRootElement = (DOMElement *)p_resultDocument->importNode(m_Root, true);
+ // Append the imported root element to the new document
+ p_DataElement->appendChild(importedRootElement);
+ // Return the appended root element
+
+ XMLString::release(&pName);
+
+ return importedRootElement;
+}
+
+cDomainSpecificInfo *cDomainSpecificInfo::ParseFromXML(DOMNode *pXMLNode, DOMElement *pXMLElement)
+{
+ std::string strName = XMLString::transcode(pXMLElement->getAttribute(ATTR_NAME));
+
+ cDomainSpecificInfo *domainInfo = new cDomainSpecificInfo(pXMLElement, strName);
+ // Return the parsed instance
+ return domainInfo;
+}
diff --git a/src/common/src/result_format/c_inertial_location.cpp b/src/common/src/result_format/c_inertial_location.cpp
index b9c02d03..3697ed78 100644
--- a/src/common/src/result_format/c_inertial_location.cpp
+++ b/src/common/src/result_format/c_inertial_location.cpp
@@ -13,9 +13,6 @@ const XMLCh *cInertialLocation::TAG_NAME = CONST_XMLCH("InertialLocation");
const XMLCh *cInertialLocation::ATTR_X = CONST_XMLCH("x");
const XMLCh *cInertialLocation::ATTR_Y = CONST_XMLCH("y");
const XMLCh *cInertialLocation::ATTR_Z = CONST_XMLCH("z");
-const XMLCh *cInertialLocation::ATTR_H = CONST_XMLCH("h");
-const XMLCh *cInertialLocation::ATTR_P = CONST_XMLCH("p");
-const XMLCh *cInertialLocation::ATTR_R = CONST_XMLCH("r");
DOMElement *cInertialLocation::WriteXML(DOMDocument *p_resultDocument)
{
@@ -24,23 +21,14 @@ DOMElement *cInertialLocation::WriteXML(DOMDocument *p_resultDocument)
XMLCh *pX = XMLString::transcode(std::to_string(m_X).c_str());
XMLCh *pY = XMLString::transcode(std::to_string(m_Y).c_str());
XMLCh *pZ = XMLString::transcode(std::to_string(m_Z).c_str());
- XMLCh *pH = XMLString::transcode(std::to_string(m_H).c_str());
- XMLCh *pP = XMLString::transcode(std::to_string(m_P).c_str());
- XMLCh *pR = XMLString::transcode(std::to_string(m_R).c_str());
p_DataElement->setAttribute(ATTR_X, pX);
p_DataElement->setAttribute(ATTR_Y, pY);
p_DataElement->setAttribute(ATTR_Z, pZ);
- p_DataElement->setAttribute(ATTR_H, pH);
- p_DataElement->setAttribute(ATTR_P, pP);
- p_DataElement->setAttribute(ATTR_R, pR);
XMLString::release(&pX);
XMLString::release(&pY);
XMLString::release(&pZ);
- XMLString::release(&pH);
- XMLString::release(&pP);
- XMLString::release(&pR);
return p_DataElement;
}
@@ -50,12 +38,8 @@ cInertialLocation *cInertialLocation::ParseFromXML(DOMNode *, DOMElement *pXMLEl
std::string strX = XMLString::transcode(pXMLElement->getAttribute(ATTR_X));
std::string strY = XMLString::transcode(pXMLElement->getAttribute(ATTR_Y));
std::string strZ = XMLString::transcode(pXMLElement->getAttribute(ATTR_Z));
- std::string strH = XMLString::transcode(pXMLElement->getAttribute(ATTR_H));
- std::string strP = XMLString::transcode(pXMLElement->getAttribute(ATTR_P));
- std::string strR = XMLString::transcode(pXMLElement->getAttribute(ATTR_R));
- cInertialLocation *result = new cInertialLocation(atof(strX.c_str()), atof(strY.c_str()), atof(strZ.c_str()),
- atof(strH.c_str()), atof(strP.c_str()), atof(strR.c_str()));
+ cInertialLocation *result = new cInertialLocation(atof(strX.c_str()), atof(strY.c_str()), atof(strZ.c_str()));
return result;
}
@@ -78,20 +62,3 @@ double cInertialLocation::GetZ() const
return m_Z;
}
-// Returns the Head
-double cInertialLocation::GetHead() const
-{
- return m_H;
-}
-
-// Returns the Pitch
-double cInertialLocation::GetPitch() const
-{
- return m_P;
-}
-
-// Returns the Roll
-double cInertialLocation::GetRoll() const
-{
- return m_R;
-}
diff --git a/src/common/src/result_format/c_issue.cpp b/src/common/src/result_format/c_issue.cpp
index 856cf3f3..d2fc0e03 100644
--- a/src/common/src/result_format/c_issue.cpp
+++ b/src/common/src/result_format/c_issue.cpp
@@ -9,6 +9,7 @@
#include "common/result_format/c_issue.h"
#include "common/result_format/c_checker.h"
#include "common/result_format/c_checker_bundle.h"
+#include "common/result_format/c_domain_specific_info.h"
#include "common/result_format/c_locations_container.h"
#include "common/util.h"
@@ -18,17 +19,20 @@ const XMLCh *cIssue::TAG_ISSUE = CONST_XMLCH("Issue");
const XMLCh *cIssue::ATTR_ISSUE_ID = CONST_XMLCH("issueId");
const XMLCh *cIssue::ATTR_DESCRIPTION = CONST_XMLCH("description");
const XMLCh *cIssue::ATTR_LEVEL = CONST_XMLCH("level");
+const XMLCh *cIssue::ATTR_RULEUID = CONST_XMLCH("ruleUID");
const std::map cIssue::issueLevelToString = {
{eIssueLevel::INFO_LVL, "Info"}, {eIssueLevel::WARNING_LVL, "Warning"}, {eIssueLevel::ERROR_LVL, "Error"}};
-cIssue::cIssue(const std::string &description, eIssueLevel infoLvl, cLocationsContainer *locationsContainer)
+cIssue::cIssue(const std::string &description, eIssueLevel infoLvl, const std::string &ruleUID,
+ cLocationsContainer *locationsContainer, cDomainSpecificInfo *domainSpecificInfo)
{
m_Description = description;
m_IssueLevel = infoLvl;
+ m_RuleUID = ruleUID;
m_Checker = nullptr;
-
AddLocationsContainer(locationsContainer);
+ AddDomainSpecificInfo(domainSpecificInfo);
}
cIssue::cIssue(const std::string &description, eIssueLevel infoLvl, std::list listLoc)
@@ -37,6 +41,20 @@ cIssue::cIssue(const std::string &description, eIssueLevel infoLvl, std::list listDomainSpecificInfo)
+ : cIssue(description, infoLvl)
+{
+ AddDomainSpecificInfo(listDomainSpecificInfo);
+}
+
+cIssue::cIssue(const std::string &description, eIssueLevel infoLvl, const std::string &ruleUID,
+ std::list listLoc)
+ : cIssue(description, infoLvl, ruleUID)
+{
+ AddLocationsContainer(listLoc);
+}
+
cIssue::~cIssue()
{
m_Checker = nullptr;
@@ -46,8 +64,14 @@ cIssue::~cIssue()
{
delete (*locIt);
}
+ for (std::list::const_iterator domIt = m_DomainSpecificInfo.cbegin();
+ domIt != m_DomainSpecificInfo.cend(); domIt++)
+ {
+ delete (*domIt);
+ }
m_Locations.clear();
+ m_DomainSpecificInfo.clear();
}
void cIssue::AddLocationsContainer(cLocationsContainer *locationsContainer)
@@ -56,11 +80,22 @@ void cIssue::AddLocationsContainer(cLocationsContainer *locationsContainer)
m_Locations.push_back(locationsContainer);
}
+void cIssue::AddDomainSpecificInfo(cDomainSpecificInfo *domainSpecificInfo)
+{
+ if (nullptr != domainSpecificInfo)
+ m_DomainSpecificInfo.push_back(domainSpecificInfo);
+}
+
void cIssue::AddLocationsContainer(std::list listLoc)
{
m_Locations.insert(m_Locations.end(), listLoc.begin(), listLoc.end());
}
+void cIssue::AddDomainSpecificInfo(std::list listDomainSpecificInfo)
+{
+ m_DomainSpecificInfo.insert(m_DomainSpecificInfo.end(), listDomainSpecificInfo.begin(),
+ listDomainSpecificInfo.end());
+}
void cIssue::AssignChecker(cChecker *checkerToAssign)
{
m_Checker = checkerToAssign;
@@ -78,10 +113,12 @@ DOMElement *cIssue::WriteXML(DOMDocument *p_resultDocument)
XMLCh *pIssueId = XMLString::transcode(std::to_string(m_Id).c_str());
XMLCh *pDescription = XMLString::transcode(m_Description.c_str());
XMLCh *pLevel = XMLString::transcode(std::to_string((int)m_IssueLevel).c_str());
+ XMLCh *pRuleUID = XMLString::transcode(m_RuleUID.c_str());
p_DataElement->setAttribute(ATTR_ISSUE_ID, pIssueId);
p_DataElement->setAttribute(ATTR_DESCRIPTION, pDescription);
p_DataElement->setAttribute(ATTR_LEVEL, pLevel);
+ p_DataElement->setAttribute(ATTR_RULEUID, pRuleUID);
// Write extended informations
if (HasLocations())
@@ -94,9 +131,21 @@ DOMElement *cIssue::WriteXML(DOMDocument *p_resultDocument)
}
}
+ // Write domain specific info
+ if (HasDomainSpecificInfo())
+ {
+ for (std::list::const_iterator domIt = m_DomainSpecificInfo.cbegin();
+ domIt != m_DomainSpecificInfo.cend(); domIt++)
+ {
+ DOMElement *domainElement = (*domIt)->WriteXML(p_resultDocument);
+ p_DataElement->appendChild(domainElement);
+ }
+ }
+
XMLString::release(&pIssueId);
XMLString::release(&pDescription);
XMLString::release(&pLevel);
+ XMLString::release(&pRuleUID);
return p_DataElement;
}
@@ -143,8 +192,9 @@ cIssue *cIssue::ParseFromXML(DOMNode *pXMLNode, DOMElement *pXMLElement, cChecke
std::string strDescription = XMLString::transcode(pXMLElement->getAttribute(ATTR_DESCRIPTION));
std::string strID = XMLString::transcode(pXMLElement->getAttribute(ATTR_ISSUE_ID));
std::string strLevel = XMLString::transcode(pXMLElement->getAttribute(ATTR_LEVEL));
+ std::string strRuleUID = XMLString::transcode(pXMLElement->getAttribute(ATTR_RULEUID));
- cIssue *issue = new cIssue(strDescription, GetIssueLevelFromStr(strLevel));
+ cIssue *issue = new cIssue(strDescription, GetIssueLevelFromStr(strLevel), strRuleUID);
issue->AssignChecker(checker);
issue->SetIssueId(strID);
@@ -168,6 +218,11 @@ cIssue *cIssue::ParseFromXML(DOMNode *pXMLNode, DOMElement *pXMLElement, cChecke
issue->AddLocationsContainer(
(cLocationsContainer *)cLocationsContainer::ParseFromXML(currentIssueNode, currentIssueElement));
}
+ // Parse cDomainSpecificInfo
+ if (Equals(currentTagName, XMLString::transcode(cDomainSpecificInfo::TAG_DOMAIN_SPECIFIC_INFO)))
+ {
+ issue->AddDomainSpecificInfo(cDomainSpecificInfo::ParseFromXML(currentIssueNode, currentIssueElement));
+ }
}
}
@@ -179,17 +234,32 @@ bool cIssue::HasLocations() const
return (m_Locations.size() != 0);
}
+bool cIssue::HasDomainSpecificInfo() const
+{
+ return (m_DomainSpecificInfo.size() != 0);
+}
+
size_t cIssue::GetLocationsCount() const
{
return m_Locations.size();
}
+size_t cIssue::GetDomainSpecificCount() const
+{
+ return m_DomainSpecificInfo.size();
+}
+
// Returns all extended informations
std::list cIssue::GetLocationsContainer() const
{
return m_Locations;
}
+std::list cIssue::GetDomainSpecificInfo() const
+{
+ return m_DomainSpecificInfo;
+}
+
eIssueLevel cIssue::GetIssueLevelFromStr(const std::string &issueLevelString)
{
return (eIssueLevel)stoi(issueLevelString);
@@ -200,6 +270,11 @@ void cIssue::SetDescription(const std::string &strDescription)
m_Description = strDescription;
}
+void cIssue::SetRuleUID(const std::string &strRuleUID)
+{
+ m_RuleUID = strRuleUID;
+}
+
void cIssue::SetLevel(eIssueLevel level)
{
m_IssueLevel = level;
@@ -211,6 +286,11 @@ std::string cIssue::GetDescription() const
return m_Description;
}
+std::string cIssue::GetRuleUID() const
+{
+ return m_RuleUID;
+}
+
// Returns the issue level
eIssueLevel cIssue::GetIssueLevel() const
{
diff --git a/src/common/src/result_format/c_locations_container.cpp b/src/common/src/result_format/c_locations_container.cpp
index b69a5b71..2a691cd5 100644
--- a/src/common/src/result_format/c_locations_container.cpp
+++ b/src/common/src/result_format/c_locations_container.cpp
@@ -12,7 +12,6 @@
#include "common/result_format/c_extended_information.h"
#include "common/result_format/c_file_location.h"
#include "common/result_format/c_inertial_location.h"
-#include "common/result_format/c_road_location.h"
#include "common/result_format/c_xml_location.h"
XERCES_CPP_NAMESPACE_USE
@@ -107,12 +106,6 @@ cLocationsContainer *cLocationsContainer::ParseFromXML(DOMNode *pXMLNode, DOMEle
subIssue->AddExtendedInformation(
(cExtendedInformation *)cXMLLocation::ParseFromXML(currentIssueNode, currentIssueElement));
}
- // Parse cRoadLocation
- else if (Equals(currentTagName, XMLString::transcode(cRoadLocation::TAG_NAME)))
- {
- subIssue->AddExtendedInformation(
- (cExtendedInformation *)cRoadLocation::ParseFromXML(currentIssueNode, currentIssueElement));
- }
// Parse cInertialLocation
else if (Equals(currentTagName, XMLString::transcode(cInertialLocation::TAG_NAME)))
{
diff --git a/src/common/src/result_format/c_metadata.cpp b/src/common/src/result_format/c_metadata.cpp
new file mode 100644
index 00000000..1ef12638
--- /dev/null
+++ b/src/common/src/result_format/c_metadata.cpp
@@ -0,0 +1,67 @@
+/**
+ * Copyright 2024, ASAM e.V.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla
+ * Public License, v. 2.0. If a copy of the MPL was not distributed
+ * with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+#include "common/result_format/c_metadata.h"
+
+XERCES_CPP_NAMESPACE_USE
+
+const XMLCh *cMetadata::TAG_NAME = CONST_XMLCH("Metadata");
+const XMLCh *cMetadata::ATTR_KEY = CONST_XMLCH("key");
+const XMLCh *cMetadata::ATTR_VALUE = CONST_XMLCH("value");
+const XMLCh *cMetadata::ATTR_DESCRIPTION = CONST_XMLCH("description");
+
+DOMElement *cMetadata::WriteXML(DOMDocument *p_resultDocument)
+{
+
+ DOMElement *p_DataElement = p_resultDocument->createElement(TAG_NAME);
+ XMLCh *pKey = XMLString::transcode(m_Key.c_str());
+ XMLCh *pValue = XMLString::transcode(m_Value.c_str());
+ XMLCh *pDescription = XMLString::transcode(m_Description.c_str());
+ p_DataElement->setAttribute(ATTR_KEY, pKey);
+ p_DataElement->setAttribute(ATTR_VALUE, pValue);
+ p_DataElement->setAttribute(ATTR_DESCRIPTION, pDescription);
+
+ XMLString::release(&pKey);
+ XMLString::release(&pValue);
+ XMLString::release(&pDescription);
+
+ return p_DataElement;
+}
+
+cMetadata *cMetadata::ParseFromXML(DOMNode *, DOMElement *pXMLElement, cChecker *checker)
+{
+ std::string strKey = XMLString::transcode(pXMLElement->getAttribute(ATTR_KEY));
+ std::string strValue = XMLString::transcode(pXMLElement->getAttribute(ATTR_VALUE));
+ std::string strDescription = XMLString::transcode(pXMLElement->getAttribute(ATTR_DESCRIPTION));
+
+ cMetadata *result = new cMetadata(strKey, strValue, strDescription);
+ result->AssignChecker(checker);
+
+ return result;
+}
+
+// Returns the key
+std::string cMetadata::GetKey() const
+{
+ return m_Key;
+}
+
+// Returns the value
+std::string cMetadata::GetValue() const
+{
+ return m_Value;
+}
+
+// Returns the description
+std::string cMetadata::GetDescription() const
+{
+ return m_Description;
+}
+void cMetadata::AssignChecker(cChecker *checkerToAssign)
+{
+ m_Checker = checkerToAssign;
+}
diff --git a/src/common/src/result_format/c_result_container.cpp b/src/common/src/result_format/c_result_container.cpp
index 9d4e42a7..613228e0 100644
--- a/src/common/src/result_format/c_result_container.cpp
+++ b/src/common/src/result_format/c_result_container.cpp
@@ -58,7 +58,6 @@ void cResultContainer::Clear()
void cResultContainer::WriteResults(const std::string &path) const
{
- XMLPlatformUtils::Initialize();
DOMImplementation *p_DOMImplementationCore = DOMImplementationRegistry::getDOMImplementation(CONST_XMLCH("core"));
// For storing a file, we need DOMImplementationLS
@@ -97,7 +96,6 @@ void cResultContainer::WriteResults(const std::string &path) const
p_DOMSerializer->release();
XMLString::release(&pPath);
- XMLPlatformUtils::Terminate();
}
/*
@@ -118,7 +116,6 @@ void cResultContainer::AddResultsFromXML(const std::string &strXmlFilePath)
}
else
{
- XMLPlatformUtils::Initialize();
xercesc::XercesDOMParser *pDomParser = new xercesc::XercesDOMParser();
pDomParser->setValidationScheme(XercesDOMParser::Val_Never);
@@ -165,7 +162,6 @@ void cResultContainer::AddResultsFromXML(const std::string &strXmlFilePath)
}
delete pDomParser;
- XMLPlatformUtils::Terminate();
}
}
diff --git a/src/common/src/result_format/c_road_location.cpp b/src/common/src/result_format/c_road_location.cpp
deleted file mode 100644
index d9e71c1d..00000000
--- a/src/common/src/result_format/c_road_location.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2023 CARIAD SE.
- *
- * This Source Code Form is subject to the terms of the Mozilla
- * Public License, v. 2.0. If a copy of the MPL was not distributed
- * with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
- */
-#include "common/result_format/c_road_location.h"
-
-XERCES_CPP_NAMESPACE_USE
-
-const XMLCh *cRoadLocation::TAG_NAME = CONST_XMLCH("RoadLocation");
-const XMLCh *cRoadLocation::ATTR_ROAD_ID = CONST_XMLCH("roadId");
-const XMLCh *cRoadLocation::ATTR_S = CONST_XMLCH("s");
-const XMLCh *cRoadLocation::ATTR_T = CONST_XMLCH("t");
-
-DOMElement *cRoadLocation::WriteXML(DOMDocument *p_resultDocument)
-{
- DOMElement *p_DataElement = CreateExtendedInformationXMLNode(p_resultDocument);
-
- XMLCh *pRoadId = XMLString::transcode(m_RoadID.c_str());
- XMLCh *pS = XMLString::transcode(std::to_string(m_S).c_str());
- XMLCh *pT = XMLString::transcode(std::to_string(m_T).c_str());
-
- p_DataElement->setAttribute(ATTR_ROAD_ID, pRoadId);
- p_DataElement->setAttribute(ATTR_S, pS);
- p_DataElement->setAttribute(ATTR_T, pT);
-
- XMLString::release(&pRoadId);
- XMLString::release(&pS);
- XMLString::release(&pT);
-
- return p_DataElement;
-}
-
-cRoadLocation *cRoadLocation::ParseFromXML(DOMNode *, DOMElement *pXMLElement)
-{
- std::string strRoadId = XMLString::transcode(pXMLElement->getAttribute(ATTR_ROAD_ID));
- std::string strS = XMLString::transcode(pXMLElement->getAttribute(ATTR_S));
- std::string strT = XMLString::transcode(pXMLElement->getAttribute(ATTR_T));
-
- cRoadLocation *result = new cRoadLocation(strRoadId, (float)atof(strS.c_str()), (float)atof(strT.c_str()));
-
- return result;
-}
-
-// Returns the xPath
-std::string cRoadLocation::GetRoadID() const
-{
- return m_RoadID;
-}
-
-// Returns the road Id as integer
-void cRoadLocation::GetRoadID(int &roadId) const
-{
- roadId = atoi(m_RoadID.c_str());
-}
-
-// Returns the s of the road
-float cRoadLocation::GetS() const
-{
- return m_S;
-}
-
-// Returns the t of the road
-float cRoadLocation::GetT() const
-{
- return m_T;
-}
diff --git a/src/common/src/result_format/c_rule.cpp b/src/common/src/result_format/c_rule.cpp
new file mode 100644
index 00000000..d6b4b1ef
--- /dev/null
+++ b/src/common/src/result_format/c_rule.cpp
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2024, ASAM e.V.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla
+ * Public License, v. 2.0. If a copy of the MPL was not distributed
+ * with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+#include "common/result_format/c_rule.h"
+
+XERCES_CPP_NAMESPACE_USE
+
+const XMLCh *cRule::TAG_NAME = CONST_XMLCH("AddressedRule");
+const XMLCh *cRule::ATTR_RULE_UID = CONST_XMLCH("ruleUID");
+
+DOMElement *cRule::WriteXML(DOMDocument *p_resultDocument)
+{
+
+ DOMElement *p_DataElement = p_resultDocument->createElement(TAG_NAME);
+ XMLCh *pRuleUID = XMLString::transcode(m_RuleUID.c_str());
+ p_DataElement->setAttribute(ATTR_RULE_UID, pRuleUID);
+
+ XMLString::release(&pRuleUID);
+
+ return p_DataElement;
+}
+
+cRule *cRule::ParseFromXML(DOMNode *, DOMElement *pXMLElement, cChecker *checker)
+{
+ std::string strRuleUID = XMLString::transcode(pXMLElement->getAttribute(ATTR_RULE_UID));
+
+ cRule *result = new cRule(strRuleUID);
+ result->AssignChecker(checker);
+
+ return result;
+}
+
+// Returns the X
+std::string cRule::GetRuleUID() const
+{
+ return m_RuleUID;
+}
+
+void cRule::AssignChecker(cChecker *checkerToAssign)
+{
+ m_Checker = checkerToAssign;
+}
diff --git a/src/report_modules/report_module_gui/src/report_format_ui.cpp b/src/report_modules/report_module_gui/src/report_format_ui.cpp
index 36d5bc4c..fc9b94bf 100644
--- a/src/report_modules/report_module_gui/src/report_format_ui.cpp
+++ b/src/report_modules/report_module_gui/src/report_format_ui.cpp
@@ -31,6 +31,7 @@ int main(int argc, char *argv[])
SetDllDirectory(currentPathW.c_str());
#endif
+ XMLPlatformUtils::Initialize();
std::string strToolpath = argv[0];
if (argc > 2)
@@ -121,6 +122,7 @@ void ShowHelp(const std::string &toolPath)
int RunReportGUI(const cParameterContainer &inputParams, const QApplication &app)
{
+ XMLPlatformUtils::Initialize();
cResultContainer *pResultContainer = new cResultContainer();
std::string strXMLResultsPath = inputParams.GetParam("strInputFile");
@@ -150,6 +152,7 @@ int RunReportGUI(const cParameterContainer &inputParams, const QApplication &app
pResultContainer->Clear();
delete pResultContainer;
+ XMLPlatformUtils::Terminate();
return execCode;
}
diff --git a/src/report_modules/report_module_gui/src/ui/c_checker_widget.cpp b/src/report_modules/report_module_gui/src/ui/c_checker_widget.cpp
index 399f89f4..8b6fc8bd 100644
--- a/src/report_modules/report_module_gui/src/ui/c_checker_widget.cpp
+++ b/src/report_modules/report_module_gui/src/ui/c_checker_widget.cpp
@@ -23,7 +23,6 @@
#include "common/result_format/c_issue.h"
#include "common/result_format/c_locations_container.h"
#include "common/result_format/c_result_container.h"
-#include "common/result_format/c_road_location.h"
#include "common/result_format/c_xml_location.h"
#include "common/util.h"
@@ -330,8 +329,7 @@ void cCheckerWidget::FillIssueTreeItem(QTreeWidgetItem *treeItem, cIssue *const
for (const auto subIssue : issue->GetLocationsContainer())
{
- if (subIssue->HasExtendedInformation() ||
- subIssue->HasExtendedInformation())
+ if (subIssue->HasExtendedInformation())
{
isVisibleInViewer = true;
}
@@ -640,8 +638,8 @@ void cCheckerWidget::ShowIssue(cIssue *const itemToShow, const cLocationsContain
ShowXOSCIssue(itemToShow, row);
}
- // Show RoadLocations and InertialLocations in Viewer
- if (extInfo->IsType() || extInfo->IsType())
+ // Show InertialLocations in Viewer
+ if (extInfo->IsType())
{
ShowIssueIn3DViewer(itemToShow, locationToShow);
}
@@ -758,15 +756,6 @@ void cCheckerWidget::PrintExtendedInformationIntoStream(cExtendedInformation *it
cXMLLocation *xmlLoc = (cXMLLocation *)item;
*ssStream << std::endl << " XPath: " << xmlLoc->GetXPath();
}
- else if (item->IsType())
- {
- cRoadLocation *roadLoc = (cRoadLocation *)item;
-
- ssStream->setf(std::ios::fixed, std::ios::floatfield);
- *ssStream << std::endl
- << " Road: id=" << roadLoc->GetRoadID() << " s=" << std::setprecision(2) << roadLoc->GetS()
- << " t=" << std::setprecision(2) << roadLoc->GetT();
- }
else if (item->IsType())
{
cInertialLocation *initialLoc = (cInertialLocation *)item;
@@ -774,8 +763,6 @@ void cCheckerWidget::PrintExtendedInformationIntoStream(cExtendedInformation *it
ssStream->setf(std::ios::fixed, std::ios::floatfield);
*ssStream << std::endl
<< " Location: x=" << std::setprecision(2) << initialLoc->GetX() << " y=" << std::setprecision(2)
- << initialLoc->GetY() << " z=" << std::setprecision(2) << initialLoc->GetZ()
- << " heading=" << std::setprecision(2) << initialLoc->GetHead() << " pitch=" << std::setprecision(2)
- << initialLoc->GetPitch() << " roll=" << std::setprecision(2) << initialLoc->GetRoll();
+ << initialLoc->GetY() << " z=" << std::setprecision(2) << initialLoc->GetZ();
}
}
diff --git a/src/report_modules/report_module_text/src/report_format_text.cpp b/src/report_modules/report_module_text/src/report_format_text.cpp
index fd78b0b5..c462a791 100644
--- a/src/report_modules/report_module_text/src/report_format_text.cpp
+++ b/src/report_modules/report_module_text/src/report_format_text.cpp
@@ -16,11 +16,11 @@
#include "common/result_format/c_locations_container.h"
#include "common/result_format/c_parameter_container.h"
#include "common/result_format/c_result_container.h"
-#include "common/result_format/c_road_location.h"
#include "common/result_format/c_xml_location.h"
#include "stdafx.h"
#include "common/qc4openx_filesystem.h"
+#include
XERCES_CPP_NAMESPACE_USE
@@ -130,6 +130,8 @@ void ShowHelp(const std::string &toolPath)
void RunTextReport(const cParameterContainer &inputParams)
{
+ XMLPlatformUtils::Initialize();
+
cResultContainer *pResultContainer = new cResultContainer();
try
@@ -176,6 +178,9 @@ void WriteResults(const char *file, cResultContainer *ptrResultContainer)
std::list bundles = ptrResultContainer->GetCheckerBundles();
std::list checkers;
std::list issues;
+ std::list rules;
+ std::set violated_rules;
+ std::set addressed_rules;
if (outFile.is_open())
{
@@ -257,14 +262,43 @@ void WriteResults(const char *file, cResultContainer *ptrResultContainer)
<< (*it_Issue)->GetDescription();
PrintExtendedInformationIntoStream((*it_Issue), &ss);
+ if ((*it_Issue)->GetRuleUID() != "")
+ {
+ violated_rules.insert((*it_Issue)->GetRuleUID());
+ }
}
ss << "\n";
}
+ // Get all rules and issues covered by the current checker
+ rules = (*itChecker)->GetRules();
+ for (std::list::const_iterator it_Rule = rules.begin(); it_Rule != rules.end(); it_Rule++)
+ {
+ if ((*it_Rule)->GetRuleUID() != "")
+ {
+ addressed_rules.insert((*it_Rule)->GetRuleUID());
+ }
+ }
}
ss << "\n" << BASIC_SEPARATOR_LINE << "\n";
}
+ ss << "Addressed vs Violated rules report \n\n";
+
+ ss << "\nTotal number of addressed rules: " << addressed_rules.size();
+ for (const auto &str : addressed_rules)
+ {
+ ss << "\n\t-> Addressed RuleUID: " << str << "\n";
+ }
+
+ ss << "\nTotal number of violated rules: " << violated_rules.size();
+ for (const auto &str : violated_rules)
+ {
+ ss << "\n\t-> Violated RuleUID: " << str << "\n";
+ }
+
+ ss << "\n" << BASIC_SEPARATOR_LINE << "\n";
+
outFile << ss.rdbuf();
outFile.close();
}
@@ -302,20 +336,12 @@ void PrintExtendedInformationIntoStream(cIssue *issue, std::stringstream *ssStre
*ssStream << "\n "
<< " XPath: " << xmlLoc->GetXPath();
}
- else if ((*extIt)->IsType())
- {
- cRoadLocation *roadLoc = (cRoadLocation *)(*extIt);
- *ssStream << "\n "
- << " Road: id=" << roadLoc->GetRoadID() << " s=" << roadLoc->GetS()
- << " t=" << roadLoc->GetT();
- }
else if ((*extIt)->IsType())
{
cInertialLocation *inertialLoc = (cInertialLocation *)(*extIt);
*ssStream << "\n "
<< " Location: x=" << inertialLoc->GetX() << " y=" << inertialLoc->GetY()
- << " z=" << inertialLoc->GetZ() << " heading=" << inertialLoc->GetHead()
- << " pitch=" << inertialLoc->GetPitch() << " roll=" << inertialLoc->GetRoll();
+ << " z=" << inertialLoc->GetZ();
}
}
}
diff --git a/src/result_pooling/src/result_pooling.cpp b/src/result_pooling/src/result_pooling.cpp
index a6f6e7f1..323f207f 100644
--- a/src/result_pooling/src/result_pooling.cpp
+++ b/src/result_pooling/src/result_pooling.cpp
@@ -14,7 +14,6 @@
#include "common/result_format/c_locations_container.h"
#include "common/result_format/c_parameter_container.h"
#include "common/result_format/c_result_container.h"
-#include "common/result_format/c_road_location.h"
#include "common/result_format/c_xml_location.h"
#include "common/xml/c_x_path_evaluator.h"
#include "stdafx.h"
@@ -73,7 +72,6 @@ int main(int argc, char *argv[])
}
RunResultPooling(inputParams, resultsDirectory);
-
return 0;
}
@@ -94,6 +92,7 @@ void ShowHelp(const std::string &toolPath)
void RunResultPooling(const cParameterContainer &inputParams, const fs::path &resultsDirectory)
{
+ XMLPlatformUtils::Initialize();
std::string strResultFile = inputParams.GetParam("strResultFile");
pResultContainer = new cResultContainer();
@@ -141,6 +140,7 @@ void RunResultPooling(const cParameterContainer &inputParams, const fs::path &re
std::cout << "Finished." << std::endl;
delete pResultContainer;
+ XMLPlatformUtils::Terminate();
}
static void AddFileLocationsToIssues()
diff --git a/test/function/CMakeLists.txt b/test/function/CMakeLists.txt
index 53d1bd0f..d63cec33 100644
--- a/test/function/CMakeLists.txt
+++ b/test/function/CMakeLists.txt
@@ -7,6 +7,7 @@
add_subdirectory(examples)
add_subdirectory(report_modules)
add_subdirectory(result_pooling/src)
+add_subdirectory(result_format/src)
if (WIN32)
# FIXME: We need some adaptions that this works in Linux
@@ -32,10 +33,15 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/runtime/files
${REFERENCE_FILES_INSTALL_DIR}/function/runtime
-
+
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/../../doc/schema
${REFERENCE_FILES_INSTALL_DIR}/doc/schema
+
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ ${CMAKE_CURRENT_SOURCE_DIR}/result_format/files
+ ${REFERENCE_FILES_INSTALL_DIR}/function/result_format
+
COMMENT "Copying test reference files..."
)
diff --git a/test/function/_common/helper.cpp b/test/function/_common/helper.cpp
index 95becd24..0a325d5f 100644
--- a/test/function/_common/helper.cpp
+++ b/test/function/_common/helper.cpp
@@ -158,8 +158,10 @@ TestResult ValidateXmlSchema(const std::string &xmlFile, const std::string &xsdF
return TestResult::ERR_NOERROR;
}
-TestResult XmlContainsNode(const std::string &xmlFile, const std::string &nodeName)
+std::vector getNodes(const std::string &xmlFile, const std::string &nodeName)
{
+ std::vector nodeList;
+
try
{
xercesc::XMLPlatformUtils::Initialize();
@@ -167,39 +169,83 @@ TestResult XmlContainsNode(const std::string &xmlFile, const std::string &nodeNa
catch (const xercesc::XMLException &e)
{
std::cerr << "Error during initialization! :\n" << xercesc::XMLString::transcode(e.getMessage()) << std::endl;
- return TestResult::ERR_FAILED;
+ return nodeList;
}
xercesc::XercesDOMParser parser;
parser.setValidationScheme(xercesc::XercesDOMParser::Val_Never);
parser.setDoNamespaces(false);
parser.setDoSchema(false);
- parser.parse(xmlFile.c_str());
+
+ try
+ {
+ parser.parse(xmlFile.c_str());
+ }
+ catch (const xercesc::XMLException &e)
+ {
+ std::cerr << "Error during parsing! :\n" << xercesc::XMLString::transcode(e.getMessage()) << std::endl;
+ xercesc::XMLPlatformUtils::Terminate();
+ return nodeList;
+ }
+ catch (const xercesc::DOMException &e)
+ {
+ std::cerr << "DOM Error during parsing! :\n" << xercesc::XMLString::transcode(e.getMessage()) << std::endl;
+ xercesc::XMLPlatformUtils::Terminate();
+ return nodeList;
+ }
+ catch (...)
+ {
+ std::cerr << "Unexpected error during parsing!" << std::endl;
+ xercesc::XMLPlatformUtils::Terminate();
+ return nodeList;
+ }
// Get the DOM document
xercesc::DOMDocument *doc = parser.getDocument();
if (!doc)
{
- std::cerr << "Unable to get DOMDocument object " << std::endl;
+ std::cerr << "Unable to get DOMDocument object" << std::endl;
xercesc::XMLPlatformUtils::Terminate();
- return TestResult::ERR_FILE_NOT_FOUND;
+ return nodeList;
}
// Convert nodeName to XMLCh*
XMLCh *xmlNodeName = xercesc::XMLString::transcode(nodeName.c_str());
- // Find the node
+ // Find the nodes
xercesc::DOMNodeList *nodes = doc->getElementsByTagName(xmlNodeName);
xercesc::XMLString::release(&xmlNodeName);
- if (nodes->getLength() > 0)
+ if (!nodes)
{
+ std::cerr << "Unable to get DOMNodeList object" << std::endl;
xercesc::XMLPlatformUtils::Terminate();
+ return nodeList;
+ }
+
+ // Store nodes in the vector
+ for (XMLSize_t i = 0; i < nodes->getLength(); ++i)
+ {
+ xercesc::DOMElement *element = static_cast(nodes->item(i));
+ if (element)
+ {
+ nodeList.push_back(element);
+ }
+ }
+
+ xercesc::XMLPlatformUtils::Terminate();
+ return nodeList;
+}
+
+TestResult XmlContainsNode(const std::string &xmlFile, const std::string &nodeName)
+{
+ std::vector nodes = getNodes(xmlFile, nodeName);
+ if (!nodes.empty())
+ {
return TestResult::ERR_NOERROR;
}
else
{
- xercesc::XMLPlatformUtils::Terminate();
return TestResult::ERR_UNKNOWN_FORMAT;
}
}
diff --git a/test/function/_common/helper.h b/test/function/_common/helper.h
index 7b6edd31..1efd7f88 100644
--- a/test/function/_common/helper.h
+++ b/test/function/_common/helper.h
@@ -8,12 +8,12 @@
#ifndef _HELPER_HEADER_
#define _HELPER_HEADER_
-#include
#include "qc4openx_filesystem.h"
#include "gtest/gtest.h"
#include
#include
#include
+#include
#include
#include
#include
@@ -39,7 +39,8 @@
*/
#define GTEST_PRINTF(_message) \
{ \
- std::cout << COLOR_GREEN << "[ ] " << COLOR_YELLOW << _message << COLOR_YELLOW << "\n" << COLOR_RESET; \
+ std::cout << COLOR_GREEN << "[ ] " << COLOR_YELLOW << _message << COLOR_YELLOW << "\n" \
+ << COLOR_RESET; \
}
/**
@@ -80,4 +81,5 @@ TestResult CheckFileExists(std::string &strResultMessage, const std::string strF
TestResult ValidateXmlSchema(const std::string &xmlFile, const std::string &xsdFile);
TestResult XmlContainsNode(const std::string &xmlFile, const std::string &nodeName);
+
#endif
diff --git a/test/function/examples/example_checker_bundle/files/result_file_ok.xqar b/test/function/examples/example_checker_bundle/files/result_file_ok.xqar
new file mode 100644
index 00000000..9816069f
--- /dev/null
+++ b/test/function/examples/example_checker_bundle/files/result_file_ok.xqar
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/function/examples/example_checker_bundle/files/result_file_wrong_status.xqar b/test/function/examples/example_checker_bundle/files/result_file_wrong_status.xqar
new file mode 100644
index 00000000..0f7119a0
--- /dev/null
+++ b/test/function/examples/example_checker_bundle/files/result_file_wrong_status.xqar
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/test/function/examples/example_checker_bundle/src/example_checker_bundle_tester.cpp b/test/function/examples/example_checker_bundle/src/example_checker_bundle_tester.cpp
index a91bde75..fded92eb 100644
--- a/test/function/examples/example_checker_bundle/src/example_checker_bundle_tester.cpp
+++ b/test/function/examples/example_checker_bundle/src/example_checker_bundle_tester.cpp
@@ -120,3 +120,54 @@ TEST_F(cTesterExampleCheckerBundle, CmdTooMuchArguments)
TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "a b");
ASSERT_TRUE(nRes == TestResult::ERR_FAILED);
}
+
+TEST_F(cTesterExampleCheckerBundle, CmdConfigContainsAddressedRuleAndMetadata)
+{
+ std::string strResultMessage;
+
+ std::string strConfigFilePath = strTestFilesDir + "/" + std::string(MODULE_NAME) + "_config.xml";
+ std::string strResultFilePath = strWorkingDir + "/" + std::string(MODULE_NAME) + ".xqar";
+
+ TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, strConfigFilePath);
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+ nRes |= CheckFileExists(strResultMessage, strResultFilePath, false);
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+
+ nRes |= XmlContainsNode(strResultFilePath, "AddressedRule");
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+
+ nRes |= XmlContainsNode(strResultFilePath, "Metadata");
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+
+ fs::remove(strResultFilePath.c_str());
+}
+
+TEST_F(cTesterExampleCheckerBundle, TestFileWrongStatus)
+{
+ std::string strResultMessage;
+
+ std::string strFilePath = strTestFilesDir + "/result_file_wrong_status.xqar";
+ std::string strXsdFilePath = strTestFilesDir + "/../../../doc/schema/xqar_report_format.xsd";
+
+ TestResult nRes = CheckFileExists(strResultMessage, strFilePath, false);
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+ nRes |= CheckFileExists(strResultMessage, strXsdFilePath, false);
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+ nRes |= ValidateXmlSchema(strFilePath, strXsdFilePath);
+ ASSERT_TRUE_EXT(nRes != TestResult::ERR_NOERROR, strResultMessage.c_str());
+}
+
+TEST_F(cTesterExampleCheckerBundle, TestFileOK)
+{
+ std::string strResultMessage;
+
+ std::string strFilePath = strTestFilesDir + "/result_file_ok.xqar";
+ std::string strXsdFilePath = strTestFilesDir + "/../../../doc/schema/xqar_report_format.xsd";
+
+ TestResult nRes = CheckFileExists(strResultMessage, strFilePath, false);
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+ nRes |= CheckFileExists(strResultMessage, strXsdFilePath, false);
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+ nRes |= ValidateXmlSchema(strFilePath, strXsdFilePath);
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+}
diff --git a/test/function/result_format/files/result_domain_info.xqar b/test/function/result_format/files/result_domain_info.xqar
new file mode 100644
index 00000000..ead85c5d
--- /dev/null
+++ b/test/function/result_format/files/result_domain_info.xqar
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/function/result_format/src/CMakeLists.txt b/test/function/result_format/src/CMakeLists.txt
new file mode 100644
index 00000000..757d48b7
--- /dev/null
+++ b/test/function/result_format/src/CMakeLists.txt
@@ -0,0 +1,41 @@
+# Copyright 2024, ASAM e.V.
+# This Source Code Form is subject to the terms of the Mozilla
+# Public License, v. 2.0. If a copy of the MPL was not distributed
+# with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+
+set(TEST_NAME result_format_tester)
+
+set_property(GLOBAL PROPERTY USE_FOLDERS true)
+
+find_package(XercesC REQUIRED)
+
+
+include_directories(${TEST_NAME} PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../_common
+ ${XercesC_INCLUDE_DIRS})
+
+add_executable(${TEST_NAME}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../_common/helper.cpp
+ ${TEST_NAME}.cpp)
+
+add_test(NAME ${TEST_NAME}
+ COMMAND ${TEST_NAME}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../
+)
+
+target_link_libraries(${TEST_NAME}
+ PRIVATE
+ GTest::gtest_main
+ $<$:stdc++fs>
+ qc4openx-common
+
+ ${XercesC_LIBRARIES}
+)
+
+target_compile_definitions(${TEST_NAME}
+ PRIVATE QC4OPENX_DBQA_BIN_DIR="${QC4OPENX_DBQA_DIR}/examples/checker_bundle_example/bin"
+ PRIVATE QC4OPENX_DBQA_RESULT_FORMAT_TEST_WORK_DIR="${CMAKE_CURRENT_BINARY_DIR}/../../"
+ PRIVATE QC4OPENX_DBQA_RESULT_FORMAT_TEST_REF_DIR="${REFERENCE_FILES_INSTALL_DIR}/function/result_format")
+
+set_target_properties(${TEST_NAME} PROPERTIES FOLDER test/function)
diff --git a/test/function/result_format/src/result_format_tester.cpp b/test/function/result_format/src/result_format_tester.cpp
new file mode 100644
index 00000000..a69291a8
--- /dev/null
+++ b/test/function/result_format/src/result_format_tester.cpp
@@ -0,0 +1,74 @@
+/**
+ * Copyright 2024, ASAM e.V.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla
+ * Public License, v. 2.0. If a copy of the MPL was not distributed
+ * with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#include "gtest/gtest.h"
+
+#include "common/result_format/c_checker_bundle.h"
+#include "common/result_format/c_domain_specific_info.h"
+#include "common/result_format/c_issue.h"
+#include "common/result_format/c_result_container.h"
+#include "helper.h"
+#include
+
+#define MODULE_NAME "ResultFormat"
+
+class cTesterResultFormat : public ::testing::Test
+{
+ public:
+ std::string strTestFilesDir = std::string(QC4OPENX_DBQA_RESULT_FORMAT_TEST_REF_DIR);
+ std::string strWorkingDir = std::string(QC4OPENX_DBQA_RESULT_FORMAT_TEST_WORK_DIR);
+};
+
+TEST_F(cTesterResultFormat, DomainSpecificInfoReadWrite)
+{
+ XERCES_CPP_NAMESPACE::XMLPlatformUtils::Initialize();
+ std::string strResultMessage;
+ std::string strFilePath = strTestFilesDir + "/result_domain_info.xqar";
+ std::string strResultFile = strWorkingDir + "/output.xqar";
+ std::string strXsdFilePath = strTestFilesDir + "/../../doc/schema/xqar_report_format.xsd";
+ // Check if xsd file exists
+ TestResult nRes = CheckFileExists(strResultMessage, strXsdFilePath, false);
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+
+ cResultContainer *pResultContainer = new cResultContainer();
+ // Parse results from xml
+ pResultContainer->AddResultsFromXML(strFilePath);
+
+ // Check domain specifc if is parsed
+ int domain_specific_info_count = 0;
+ std::list checkerBundles = pResultContainer->GetCheckerBundles();
+ for (std::list::const_iterator itCheckerBundle = checkerBundles.cbegin();
+ itCheckerBundle != checkerBundles.cend(); itCheckerBundle++)
+ {
+ std::list issues = (*itCheckerBundle)->GetIssues();
+ for (std::list::const_iterator itIssue = issues.cbegin(); itIssue != issues.cend(); itIssue++)
+ {
+ domain_specific_info_count += (*itIssue)->GetDomainSpecificCount();
+ }
+ }
+
+ std::cout << "Domain specific info count : " << domain_specific_info_count << std::endl;
+ ASSERT_TRUE_EXT(domain_specific_info_count > 0, "No domain specific info found");
+
+ // Write results to XML
+ pResultContainer->WriteResults(strResultFile);
+
+ // Check if output file exists
+ nRes |= CheckFileExists(strResultMessage, strResultFile, false);
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+ // Check if result file is valid according to xsd
+ nRes |= ValidateXmlSchema(strResultFile, strXsdFilePath);
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+
+ // Check if result file contains a specific tag
+ nRes |= XmlContainsNode(strFilePath, "RoadLocation");
+ ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str());
+
+ delete pResultContainer;
+ XERCES_CPP_NAMESPACE::XMLPlatformUtils::Terminate();
+}