diff --git a/pull_request_template.md b/.github/pull_request_template.md similarity index 100% rename from pull_request_template.md rename to .github/pull_request_template.md diff --git a/.github/workflows/build-on-change-linux.yaml b/.github/workflows/build-on-change-linux.yaml new file mode 100644 index 00000000..e03b885f --- /dev/null +++ b/.github/workflows/build-on-change-linux.yaml @@ -0,0 +1,68 @@ +name: Build framework on Linux + +on: + # execute on every PR made targeting the branches bellow + pull_request: + branches: + - master + - develop # can be removed on master merge + paths: # we only include paths critical for building to avoid unnecessary runs + - src/** + - include/** + - scripts/cmake/** + - tests/** + - .github/workflows/** + - doc/** + - runtime/** + - docker/** + + # execute on every push made targeting the branches bellow + push: + branches: + - master + - develop # can be removed on master merge + paths: # we only include paths critical for building to avoid unnecessary runs + - src/** + - include/** + - scripts/cmake/** + - .github/workflows/** + - doc/** + - runtime/** + - docker/** + +jobs: + build-linux: + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - 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 . + + - name: Unit test execution + if: github.event_name == 'pull_request' + run: | + docker run -v ${{ github.workspace }}:/out --name unit_test unit_test + + - name: Archive unit test results + if: github.event_name == 'pull_request' && (success() || failure()) + uses: actions/upload-artifact@v4 + 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 new file mode 100644 index 00000000..19f5a70e --- /dev/null +++ b/.github/workflows/build-on-change-windows.yaml @@ -0,0 +1,152 @@ +name: Build framework on Windows + +on: + # execute on every PR made targeting the branches bellow + pull_request: + branches: + - master + - develop # can be removed on master 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: + - master + - develop # can be removed on master merge + paths: # we only include paths critical for building to avoid unnecessary runs + - src/** + - include/** + - scripts/cmake/** + - .github/workflows/** + - doc/** + - runtime/** + - docker/** + +jobs: + build-windows: + runs-on: windows-2019 + env: + TEST_ENABLED: ${{ github.event_name == 'pull_request' && 'ON' || 'OFF' }} + WORKING_PATH: "D:\\a" + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v2 + + - name: Install Qt + uses: jurplel/install-qt-action@v4.0.0 + with: + version: 5.15.2 + host: windows + target: desktop + arch: win64_msvc2019_64 + + - name: Install gtest + if: github.event_name == 'pull_request' + env: + CXX: g++-10 + run: | + Write-Output "Installing gtest..." + + git clone https://github.com/google/googletest.git -b release-1.10.0 + cd googletest + mkdir build + cd build + cmake -G "Visual Studio 16 2019" ` + -Dgtest_force_shared_crt=ON ` + -DCMAKE_INSTALL_PREFIX="$env:WORKING_PATH\gtest-Out" .. + cmake --build . --config Release + cmake --build . --config Release --target install + + Write-Output "Gtest installed." + shell: pwsh + + - name: Install XercesC + run: | + Write-Output "Setting up Xerces-C++..." + $xercesZip = "$env:WORKING_PATH\xerces-c-3.2.5.zip" + Invoke-WebRequest -Uri "https://dlcdn.apache.org/xerces/c/3/sources/xerces-c-3.2.5.zip" -OutFile $xercesZip + Expand-Archive -Path $xercesZip -DestinationPath "$env:WORKING_PATH" + cd "$env:WORKING_PATH\xerces-c-3.2.5" + mkdir build + cd build + cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_PREFIX="$env:WORKING_PATH\Xerces-Out" .. + cmake --build . --config Debug + cmake --build . --config Debug --target install + + Add-Content $env:GITHUB_PATH "$env:WORKING_PATH\bin\xerces-c_3_2D.dll" + Add-Content $env:GITHUB_PATH "$env:WORKING_PATH\Xerces-Out\include" + Add-Content $env:GITHUB_PATH "$env:WORKING_PATH\Xerces-Out\bin" + + shell: pwsh + + - name: Build framework + run: | + Write-Output "Setting up QC-Framework..." + + cd "$env:WORKING_PATH\qc-framework\qc-framework" + mkdir build + + cmake -H"$env:WORKING_PATH\qc-framework\qc-framework" -S. -Bbuild ` + -G "Visual Studio 16 2019" -A x64 -T v142 ` + -DCMAKE_INSTALL_PREFIX="$env:WORKING_PATH\QC-Framework-Out" ` + -DENABLE_FUNCTIONAL_TESTS="$env:TEST_ENABLED" ` + -DGTest_ROOT="$env:WORKING_PATH\gtest-Out" ` + -DQt5_ROOT="$env:Qt5_DIR\Qt5\" ` + -DXercesC_ROOT="$env:WORKING_PATH\Xerces-Out" + + cmake --build build --target ALL_BUILD --config Release + + cmake --install build + + # Final output + Write-Output "All installations and setups are complete!" + shell: pwsh + + - name: Unit test execution + if: github.event_name == 'pull_request' + run: | + Write-Output "Starting unit tests..." + + cd "$env:WORKING_PATH\qc-framework\qc-framework" + + ctest --test-dir build -C Release + + 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 + with: + name: test-report + path: ${{ github.workspace }}\build\Testing\Temporary\LastTest.log + + - name: Runtime test execution + if: github.event_name == 'pull_request' + run: | + 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" + + 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/CMakeLists.txt b/CMakeLists.txt index 7333b208..5afec7db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,8 +19,6 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) -add_definitions( -DDEV_ESSENTIAL_DISABLE_MAKE_RESULT_CHECK_RESERVED_ZERO=1 -DDEV_ESSENTIAL_DISABLE_DEPRECATED_WARNINGS=1) - file(STRINGS version QC4OPENX_VERSION LIMIT_COUNT 1) project(qc4openx VERSION ${QC4OPENX_VERSION}) @@ -44,7 +42,6 @@ elseif() -Wall -Wextra -Wno-reorder -Wno-sign-compare) endif() -find_package(dev_essential REQUIRED) find_package(XercesC REQUIRED) # QT diff --git a/INSTALL.md b/INSTALL.md index c467e630..bf565dc7 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -18,7 +18,6 @@ The ASAM Quality Checker Framework runs on Linux and Windows. ## 3rd Party Dependencies -- dev_essential - Xerces-C++ - Qt 5 - **Optional:** GoogleTest (only if tests are enabled) @@ -83,7 +82,6 @@ $ cmake -G "Visual Studio 16 2019" -A "x64" -T "v142" -B../build -S. ^ -DASAM_OPENDRIVE_XSD_DIR="" ^ -DASAM_OPENSCENARIO_XSD_DIR="" ^ -DXERCES_ROOT="" ^ - -Ddev_essential_ROOT="" ^ -DQt5_ROOT="" $ cmake --build ../build --target ALL_BUILD --config Release $ ctest --test-dir ../build -C Release @@ -101,7 +99,6 @@ With the following CMake values: files for OpenSCENARIO downloaded from the ASAM website (multiple versions of the schema files in this directory are supported). - _\_: The root dir of the pre-built Xerces-C++ package -- _\_: The root dir of the pre-built dev_essential package - _\_: The root dir of the pre-built qt5 package ### Options diff --git a/doc/schema/xqar_report_format.xsd b/doc/schema/xqar_report_format.xsd index 8e1042f8..c4296f82 100644 --- a/doc/schema/xqar_report_format.xsd +++ b/doc/schema/xqar_report_format.xsd @@ -24,7 +24,7 @@ with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - + @@ -61,7 +61,7 @@ with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - + diff --git a/docker/Dockerfile.linux b/docker/Dockerfile.linux new file mode 100644 index 00000000..9278ac52 --- /dev/null +++ b/docker/Dockerfile.linux @@ -0,0 +1,82 @@ +# 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/. + +FROM ubuntu:22.04 AS framework_builder + +SHELL ["/bin/bash", "-c"] + +RUN echo "Installing Dependencies..." && \ + apt update && apt install -y \ + g++ \ + g++-10 \ + make \ + build-essential \ + cmake \ + libgtest-dev \ + qtbase5-dev \ + libqt5xmlpatterns5-dev \ + libxerces-c-dev \ + pkg-config && \ + echo "Dependencies installed." + +RUN mkdir -p /app/framework + +COPY examples /app/framework/examples +COPY include /app/framework/include +COPY scripts /app/framework/scripts +COPY src /app/framework/src +COPY test /app/framework/test +COPY doc /app/framework/doc +COPY CMakeLists.txt /app/framework/CMakeLists.txt +COPY version /app/framework/version +COPY licenses /app/framework/licenses +COPY runtime /app/framework/runtime + +RUN echo "Building framework..." && \ + cd /app/framework && \ + cmake -G "Unix Makefiles" -B./build -S . \ + -DCMAKE_INSTALL_PREFIX="/home/$(whoami)/qc-build" \ + -DENABLE_FUNCTIONAL_TESTS=ON -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." + + +# Runtime stage +FROM python:3.11.9-slim-bookworm as runtime_test + +RUN echo "Installing Qt..." && \ + apt update && apt install -y \ + qtbase5-dev \ + libqt5xmlpatterns5-dev \ + libxerces-c-dev \ + pkg-config && \ + 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 + +# @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 + +WORKDIR /app/framework/runtime/ + +CMD 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/ diff --git a/docker/test_runtime.sh b/docker/test_runtime.sh new file mode 100755 index 00000000..d16de66c --- /dev/null +++ b/docker/test_runtime.sh @@ -0,0 +1,29 @@ +# 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 OUTPUT_DIR=$1 + +cd .. + +DOCKER_BUILDKIT=1 \ + docker build \ + -f docker/Dockerfile.linux \ + --target runtime_test \ + -t runtime_test . + +DOCKER_BUILDKIT=1 \ + docker build \ + -f docker/Dockerfile.linux \ + --target unit_test \ + -t unit_test . + +docker run \ + -v "$OUTPUT_DIR":/out \ + --rm --name runtime_test runtime_test + +docker run --rm \ + -v "$OUTPUT_DIR":/out \ + --name unit_test unit_test + diff --git a/examples/checker_bundle_example/CMakeLists.txt b/examples/checker_bundle_example/CMakeLists.txt index 82369329..1d28a8f9 100644 --- a/examples/checker_bundle_example/CMakeLists.txt +++ b/examples/checker_bundle_example/CMakeLists.txt @@ -20,7 +20,7 @@ add_executable(${EXAMPLE_CHECKER_BUNDLE} src/main.cpp ) -target_link_libraries(${EXAMPLE_CHECKER_BUNDLE} PRIVATE qc4openx-common) +target_link_libraries(${EXAMPLE_CHECKER_BUNDLE} PRIVATE qc4openx-common $<$:stdc++fs>) install(TARGETS ${EXAMPLE_CHECKER_BUNDLE} DESTINATION examples/checker_bundle_example/bin) qc4openx_install_qt(examples/checker_bundle_example/bin ${EXAMPLE_CHECKER_BUNDLE}.exe) diff --git a/examples/viewer_example/CMakeLists.txt b/examples/viewer_example/CMakeLists.txt index aaae7ec9..2e713763 100644 --- a/examples/viewer_example/CMakeLists.txt +++ b/examples/viewer_example/CMakeLists.txt @@ -19,7 +19,7 @@ include_directories(${VIEWER} PRIVATE ) add_library(${VIEWER} SHARED viewer_example.cpp) -target_link_libraries(${VIEWER} PRIVATE qc4openx-common) +target_link_libraries(${VIEWER} PRIVATE qc4openx-common $<$:stdc++fs>) install( TARGETS ${VIEWER} diff --git a/licenses/3rd_party_terms_and_licenses/dev_essential_LICENSE b/licenses/3rd_party_terms_and_licenses/dev_essential_LICENSE deleted file mode 100644 index 9203022c..00000000 --- a/licenses/3rd_party_terms_and_licenses/dev_essential_LICENSE +++ /dev/null @@ -1,400 +0,0 @@ -==================================================================== - -Project: dev_essential - -The following list contains attribution notices, among them, where applicable, attribution notices of various relevant modules. - -==================================================================== - - -********************************************************************* -pugixml -********************************************************************* -## License -This library is available to anybody free of charge, under the terms of MIT License: - - Copyright (c) 2006-2016 Arseny Kapoulkine - - Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - - The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. ----- -* Copyright (C) 2006-2016, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) -* Report bugs and download new versions at http://pugixml.org/ -* -* This library is distributed under the MIT License. See notice at the end -* of this file. -* -* This work is based on the pugxml parser, which is: -* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) ---- -* Boost.Foreach support for pugixml classes. -* This file is provided to the public domain. -* Written by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) ---- -This software is based on pugixml library (http://pugixml.org). -pugixml is Copyright (C) 2006-2016 Arseny Kapoulkine. ---- - - -********************************************************************* -clara -********************************************************************* -// Copyright 2017 Two Blue Cubes Ltd. All rights reserved. -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See https://github.com/philsquared/Clara for more details - - ---- - - -// A single-header library for wrapping and laying out basic text, by Phil Nash -// -// This work is licensed under the BSD 2-Clause license. -// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause -// -// This project is hosted at https://github.com/philsquared/textflowcpp - - ---- - - -Boost Software License - Version 1.0 - August 17th, 2003 - - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - ---- - - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - ---- - - -  - - - - -********************************************************************* -UTFCPP 2.3 -********************************************************************* -// Copyright 2006 Nemanja Trifunovic - - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - - - -********************************************************************* -OSSP uuid -********************************************************************* -## OSSP uuid - Universally Unique Identifier -## Copyright (c) 2004-2008 Ralf S. Engelschall -## Copyright (c) 2004-2008 The OSSP Project -## -## This file is part of OSSP uuid, a library for the generation -## of UUIDs which can found at http://www.ossp.org/pkg/lib/uuid/ -## -## Permission to use, copy, modify, and distribute this software for -## any purpose with or without fee is hereby granted, provided that -## the above copyright notice and this permission notice appear in all -## copies. -## -## THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED -## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR -## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -## SUCH DAMAGE. -## -## uuid.pod: manual page - - --- - - * RSA Data Security, Inc., MD5 message-digest algorithm -* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. -* All rights reserved. -* -* License to copy and use this software is granted provided that it -* is identified as the "RSA Data Security, Inc. MD5 Message-Digest -* Algorithm" in all material mentioning or referencing this software -* or this function. -* -* License is also granted to make and use derivative works provided -* that such works are identified as "derived from the RSA Data -* Security, Inc. MD5 Message-Digest Algorithm" in all material -* mentioning or referencing the derived work. -* -* RSA Data Security, Inc. makes no representations concerning either -* the merchantability of this software or the suitability of this -* software for any particular purpose. It is provided "as is" -* without express or implied warranty of any kind. -* -* These notices must be retained in any copies of any part of this -* documentation and/or software. - - --- - - dnl ## SA - OSSP Socket Abstraction Library -dnl ## Copyright (c) 2001-2003 Ralf S. Engelschall -dnl ## Copyright (c) 2001-2003 The OSSP Project -dnl ## Copyright (c) 2001-2003 Cable & Wireless Deutschland -dnl ## -dnl ## This file is part of OSSP SA, a socket abstraction library which -dnl ## can be found at http://www.ossp.org/pkg/sa/. -dnl ## -dnl ## Permission to use, copy, modify, and distribute this software for -dnl ## any purpose with or without fee is hereby granted, provided that -dnl ## the above copyright notice and this permission notice appear in all -dnl ## copies. -dnl ## -dnl ## THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED -dnl ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -dnl ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -dnl ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR -dnl ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -dnl ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -dnl ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -dnl ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -dnl ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -dnl ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -dnl ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -dnl ## SUCH DAMAGE. - - --- - - * Copyright Patrick Powell 1995 -* This code is based on code written by Patrick Powell -* It may be used for any purpose as long as this notice remains intact -* on all source code distributions. - - * This code contains numerious changes and enhancements which were -* made by lots of contributors over the last years to Patrick Powell's -* original code: -* -* o Patrick Powell (1995) -* o Brandon Long (1996, for Mutt) -* o Thomas Roessler (1998, for Mutt) -* o Michael Elkins (1998, for Mutt) -* o Andrew Tridgell (1998, for Samba) -* o Luke Mewburn (1999, for LukemFTP) -* o Ralf S. Engelschall (1999, for OSSP) - - --- - - ** OSSP ui128 - 128-Bit Arithmetic -** Copyright (c) 2002-2005 Ralf S. Engelschall -** Copyright (c) 2002-2005 The OSSP Project -** -** This file is part of OSSP ui128, a 128-bit arithmetic library -** which can be found at http://www.ossp.org/pkg/lib/ui128/. -** -** Permission to use, copy, modify, and distribute this software for -** any purpose with or without fee is hereby granted, provided that -** the above copyright notice and this permission notice appear in all -** copies. -** -** THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED -** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR -** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -** SUCH DAMAGE. - - --- - - ## OSSP uuid - Universally Unique Identifier -## Copyright (c) 2004-2007 Ralf S. Engelschall -## Copyright (c) 2004-2007 The OSSP Project - - ## Copyright (c) 2004 Piotr Roszatycki -## -## This file is part of OSSP uuid, a library for the generation -## of UUIDs which can found at http://www.ossp.org/pkg/lib/uuid/ -## -## Permission to use, copy, modify, and distribute this software for -## any purpose with or without fee is hereby granted, provided that -## the above copyright notice and this permission notice appear in all -## copies. -## -## THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED -## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR -## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -## SUCH DAMAGE. - - --- - -This software contains the "RSA Data Security, Inc. MD5 Message-Digest Algorithm". -This work is derived from the "RSA Data Security, Inc. MD5 Message-Digest Algorithm". - - --- - -   - - - - -********************************************************************* -Boost.CurrentFunction -********************************************************************* -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt -// -// http://www.boost.org/libs/assert/current_function.html - - ---- - - -Boost Software License - Version 1.0 - August 17th, 2003 - - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - - - - -==================================================================== -Attachment -==================================================================== - - -********************************************************************* -Boost Software License 1.0 -********************************************************************* -Boost Software License - Version 1.0 - August 17th, 2003 - - Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: - - The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - diff --git a/licenses/readme.md b/licenses/readme.md index 6959c09a..37232d4b 100644 --- a/licenses/readme.md +++ b/licenses/readme.md @@ -11,11 +11,6 @@ with this file, You can obtain one at https://mozilla.org/MPL/2.0/. This software is licensed under [MPL - Mozilla Public License - Version 2.0](https://mozilla.org/MPL/2.0/) and uses the following 3rd party components. -## dev_essential - -- [dev_essential_LICENSE](./3rd_party_terms_and_licenses/dev_essential_LICENSE) -- Download source: - ## GoogleTest diff --git a/runtime/README.md b/runtime/README.md new file mode 100644 index 00000000..eeedbae7 --- /dev/null +++ b/runtime/README.md @@ -0,0 +1,47 @@ +# Runtime module + +The runtime module is responsible of executing the qc-framework modules specified in an input configuration file. + +Input configuration file need to respect the [config xsd schema](../doc/schema/config_format.xsd) + +The runtime module execute the following steps: + +1. Validate input xml file given the config_format.xsd schema +2. For each checker bundle specified in configuration, execute its process +3. Execute result pooling for collect results from all checker bundle executed in step 2 +4. For each report module specified in configuration, execute its process + +## Installation & Usage + +The runtime module is implemented in the [python script runtime.py](./runtime/runtime.py) + +In order to use the runtime, you can set up a virtual environment using your preferred python 3.6+ e.g. with 3.8 + +``` +python3.8 -m venv runtime_env +``` + +activate it and install the required dependencies + +``` +source runtime_env/bin/activate + +pip3 install -r requirements.txt +``` + +Then from the same terminal you can execute the runtime: + +``` +python3 runtime/runtime.py --config=$PATH_TO_CONFIG_XML --install_dir=$PATH_TO_EXE --schema_dir=$PATH_TO_XSD +``` + +where + +- `$PATH_TO_CONFIG_XML` points to an xml file following the [config xsd schema](../doc/schema/config_format.xsd) +- `$PATH_TO_EXE` points to the folder where framework executables are installed +- `$PATH_TO_XSD` points to a folder containig the config_format.xsd file + +#### Note + +- `$PATH_TO_EXE` and `$PATH_TO_XSD` args are temporarily supported until better handling of external directory will be implemented + diff --git a/runtime/requirements.txt b/runtime/requirements.txt new file mode 100644 index 00000000..15559a0c --- /dev/null +++ b/runtime/requirements.txt @@ -0,0 +1,2 @@ +lxml==5.0.0 +pytest==8.2.1 diff --git a/runtime/runtime/__init__.py b/runtime/runtime/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/runtime/runtime/runtime.py b/runtime/runtime/runtime.py new file mode 100644 index 00000000..dc8a046e --- /dev/null +++ b/runtime/runtime/runtime.py @@ -0,0 +1,221 @@ +# 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 subprocess +from lxml import etree +import sys, os +import argparse +from typing import List + + +def on_windows() -> bool: + """Check if script is executed in Windows OS + + Returns: + bool: True if executing the script on Windows + """ + return os.name == "nt" + + +def check_executable_exists(executable: str) -> bool: + """Check if specified executable exists in current working directory + + Args: + executable (str): executable name to find + + Returns: + bool: True if executable exists + """ + return executable in list_files_in_cwd() + + +def is_valid_xml(xml_file: str, schema_file: str) -> bool: + """Check if input xml file (.xml) is valid against the input schema file (.xsd) + + Args: + xml_file (str): XML file path to test + schema_file (str): XSD file path containing the schema for the validation + + Returns: + bool: True if file pointed by xml_file is valid w.r.t. input schema file. False otherwise + """ + with open(schema_file, "rb") as schema_f: + schema_doc = etree.parse(schema_f) + schema = etree.XMLSchema(schema_doc) + + with open(xml_file, "rb") as xml_f: + xml_doc = etree.parse(xml_f) + + if schema.validate(xml_doc): + print("XML is valid.") + return True + else: + print("XML is invalid!") + for error in schema.error_log: + print(error.message) + return False + + +def run_command(cmd_list: List[str]) -> None: + """Execute command specified in cmd_list list parameter + + Args: + cmd_list (List): A list containing all the strings that constitutes the command to execute + E.g. cmd_list = ["python3", "script.py", "--help"] + + """ + try: + print(f"Executing command: {' '.join(cmd_list)}") + process = subprocess.Popen( + cmd_list, 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()) + except Exception as e: + print(f"Error: {str(e)}") + + +def list_files_in_cwd() -> List[str]: + """List all files in current working directory + + Returns: + List: List with all the executables found in working directory + """ + cwd = os.getcwd() + files = os.listdir(cwd) + files = [f for f in files if os.path.isfile(os.path.join(cwd, f))] + return files + + +def get_os_command_from_app_name(app_name: str) -> str: + """Get command to execute the specified app_name as input + + The function checks the operating system and build the returning command needed + e.g. app_name: HelloWorld + if the script is executed on Linux the result is "./HelloWorld" + if on Windows the result is HelloWorld.exe + + Args: + app_name (str): The executable name that needs to be decorated with required chars + + Returns: + str: A ready to execute string representation of app_name considering the current OS requirements. + """ + os_command = None + + if on_windows(): + app_name = app_name + ".exe" + os_command = app_name + else: + os_command = "./" + app_name + + if not check_executable_exists(app_name): + print(f"Executable {app_name} does not exist!\nAbort...") + sys.exit() + + return os_command + + +def run_commands_from_xml(xml_file: str, install_folder: str) -> None: + """Execute the qc-framework runtime steps specified in the input xml file + + The function: + - For each checker bundle specified in configuration, execute its process + - Execute result pooling for collect results from all checker bundle executed in step 2 + - For each report module specified in configuration, execute its process + Args: + xml_file (str): input configuration xml file + install_folder (str): folder where executables specified in the input xml files are installed + """ + + root = etree.parse(xml_file) + + print("Executable found in install directory: ", list_files_in_cwd()) + + # 1. Execute all CheckerBundle + print("#" * 50) + print("1. Execute all CheckerBundle") + print("#" * 50) + for element in root.findall(".//CheckerBundle"): + app_name = element.get("application") + os_command = get_os_command_from_app_name(app_name) + cmd_list = [os_command, xml_file] + run_command(cmd_list) + + # 2. Execute ResultPooling + print("#" * 50) + print("2. Execute ResultPooling") + print("#" * 50) + app_name = "ResultPooling" + os_command = get_os_command_from_app_name(app_name) + run_command([os_command]) + + # 3. Execute Report Modules + print("#" * 50) + print("3. Execute Report Modules") + print("#" * 50) + for element in root.findall(".//ReportModule"): + app_name = element.get("application") + os_command = get_os_command_from_app_name(app_name) + cmd_list = [os_command, xml_file] + run_command(cmd_list) + + +def execute_runtime(xml_file: str, install_folder: str, schema_folder: str): + """Execute all runtime operations on input xml file + + Before executing all the steps, the xml_file is validated using the schema_folde/config_format.xsd schema file + + Args: + xml_file (str): input configuration xml file + install_folder (str): folder where executables specified in the input xml files are installed + schema_folder (str): folder where schema files are located to load the config_format.xsd file used in validation + """ + os.chdir(install_folder) + + schema_file = os.path.join(schema_folder, "config_format.xsd") + if not is_valid_xml(xml_file, schema_file): + print("Aborting due to invalid XML.") + sys.exit() + + run_commands_from_xml(xml_file, install_folder) + + +def main(): + parser = argparse.ArgumentParser(description="Process XML configuration file.") + parser.add_argument( + "--config", + type=str, + help="Path to the XML configuration file", + required=True, + ) + parser.add_argument( + "--install_dir", + type=str, + help="Path where compiled binaries are installed", + required=True, + ) + parser.add_argument( + "--schema_dir", + type=str, + help="Path to the XSD schema for validation", + required=True, + ) + + args = parser.parse_args() + + execute_runtime(args.config, args.install_dir, args.schema_dir) + + +if __name__ == "__main__": + main() diff --git a/runtime/tests/__init__.py b/runtime/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/runtime/tests/test_data/DemoCheckerBundle_config.xml b/runtime/tests/test_data/DemoCheckerBundle_config.xml new file mode 100644 index 00000000..25f92817 --- /dev/null +++ b/runtime/tests/test_data/DemoCheckerBundle_config.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/runtime/tests/test_runtime.py b/runtime/tests/test_runtime.py new file mode 100644 index 00000000..7b909fc8 --- /dev/null +++ b/runtime/tests/test_runtime.py @@ -0,0 +1,95 @@ +# 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 pytest +import runtime.runtime as runtime +import os +import subprocess +from lxml import etree +from typing import List + + +def is_valid_xml(xml_file: str, schema_file: str) -> bool: + """Check if input xml file (.xml) is valid against the input schema file (.xsd) + + Args: + xml_file (str): XML file path to test + schema_file (str): XSD file path containing the schema for the validation + + Returns: + bool: True if file pointed by xml_file is valid w.r.t. input schema file. False otherwise + """ + with open(schema_file, "rb") as schema_f: + schema_doc = etree.parse(schema_f) + schema = etree.XMLSchema(schema_doc) + + with open(xml_file, "rb") as xml_f: + xml_doc = etree.parse(xml_f) + + if schema.validate(xml_doc): + print("XML is valid.") + return True + else: + print("XML is invalid!") + for error in schema.error_log: + print(error.message) + return False + + +def check_node_exists(xml_file: str, node_name: str) -> bool: + """Check if input node node_name is present in xml document specified in xml_file + + Args: + xml_file (str): XML file path to inspect + node_name (str): Name of the node to search in the xml doc + + Returns: + bool: True if node at least 1 node called node_name is found in the xml file + """ + # Parse the XML document + tree = etree.parse(xml_file) + # Use XPath to search for the node + nodes = tree.xpath(f'//*[local-name()="{node_name}"]') + return len(nodes) > 0 + + +def test_runtime_execution(): + + install_dir = os.path.join("..", "build", "bin") + os.chdir(install_dir) + + config_xml = os.path.join( + "..", "..", "runtime", "tests", "test_data", "DemoCheckerBundle_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 result file follows its xsd schema + xsd_file = os.path.join(schema_dir, "xqar_report_format.xsd") + assert is_valid_xml(result_file, xsd_file) + # Check that at least one node called "Issue" is present in the result + node_name = "Issue" + assert check_node_exists(result_file, node_name) diff --git a/src/report_modules/report_module_gui/CMakeLists.txt b/src/report_modules/report_module_gui/CMakeLists.txt index 04c507e7..368bf41f 100644 --- a/src/report_modules/report_module_gui/CMakeLists.txt +++ b/src/report_modules/report_module_gui/CMakeLists.txt @@ -22,11 +22,10 @@ add_executable(${REPORT_MODULE_GUI_PROJECT} target_link_libraries(${REPORT_MODULE_GUI_PROJECT} PRIVATE qc4openx-common - dev_essential::result - dev_essential::system Qt5::Gui Qt5::Widgets $<$:dl> + $<$:stdc++fs> ) install(TARGETS ${REPORT_MODULE_GUI_PROJECT} DESTINATION bin) 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 bf4a0ee2..36d5bc4c 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 @@ -13,11 +13,11 @@ #include "common/config_format/c_configuration.h" #include "common/config_format/c_configuration_report_module.h" +#include "common/qc4openx_filesystem.h" #include "common/result_format/c_parameter_container.h" #include "common/result_format/c_result_container.h" #include "report_format_ui.h" #include "ui/c_report_module_window.h" -#include XERCES_CPP_NAMESPACE_USE @@ -25,8 +25,10 @@ XERCES_CPP_NAMESPACE_USE int main(int argc, char *argv[]) { #ifdef WIN32 - auto workdir = a_util::filesystem::getWorkingDirectory(); - SetDllDirectoryA(workdir.toString().c_str()); + auto currentPath = std::filesystem::current_path(); + auto currentPathW = currentPath.string(); + // Set the DLL directory + SetDllDirectory(currentPathW.c_str()); #endif std::string strToolpath = argv[0]; diff --git a/src/report_modules/report_module_gui/src/ui/c_report_module_window.cpp b/src/report_modules/report_module_gui/src/ui/c_report_module_window.cpp index 15063b9d..115bc870 100644 --- a/src/report_modules/report_module_gui/src/ui/c_report_module_window.cpp +++ b/src/report_modules/report_module_gui/src/ui/c_report_module_window.cpp @@ -12,7 +12,6 @@ #endif #include "c_report_module_window.h" -#include #include "c_checker_widget.h" #include "c_xodr_editor_widget.h" diff --git a/src/report_modules/report_module_text/CMakeLists.txt b/src/report_modules/report_module_text/CMakeLists.txt index e5918940..623c32c0 100644 --- a/src/report_modules/report_module_text/CMakeLists.txt +++ b/src/report_modules/report_module_text/CMakeLists.txt @@ -14,7 +14,7 @@ add_executable(${REPORT_MODULE_TEXT_PROJECT} src/report_format_text.cpp ) -target_link_libraries(${REPORT_MODULE_TEXT_PROJECT} PRIVATE qc4openx-common) +target_link_libraries(${REPORT_MODULE_TEXT_PROJECT} PRIVATE qc4openx-common $<$:stdc++fs>) install(TARGETS ${REPORT_MODULE_TEXT_PROJECT} DESTINATION bin) qc4openx_install_qt(bin ${REPORT_MODULE_TEXT_PROJECT}${CMAKE_EXECUTABLE_SUFFIX}) diff --git a/src/result_pooling/CMakeLists.txt b/src/result_pooling/CMakeLists.txt index c31f380a..5ca662a8 100644 --- a/src/result_pooling/CMakeLists.txt +++ b/src/result_pooling/CMakeLists.txt @@ -18,6 +18,7 @@ target_link_libraries(${RESULT_POOLING_PROJECT} PRIVATE qc4openx-common Qt5::Network Qt5::XmlPatterns + $<$:stdc++fs> ) install(TARGETS ${RESULT_POOLING_PROJECT} DESTINATION bin) diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index ba9cacc6..009733c6 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -8,7 +8,6 @@ set(RUNTIME_PROJECT "ConfigGUI") project(${RUNTIME_PROJECT}) set(CMAKE_AUTOMOC ON) -qt5_add_resources(Resources res/POC_Runtime.qrc) add_executable(${RUNTIME_PROJECT} src/c_configuration_validator.cpp @@ -21,18 +20,15 @@ add_executable(${RUNTIME_PROJECT} src/ui/c_param_dialog.cpp src/ui/c_local_param_dialog.cpp src/ui/c_global_param_dialog.cpp - src/ui/c_process_log.cpp src/ui/c_process_view.cpp - src/ui/c_runtime_control.cpp - src/ui/c_runtime_thread.cpp src/ui/c_runtime_window.cpp - ${Resources} ) target_link_libraries(${RUNTIME_PROJECT} PRIVATE qc4openx-common Qt5::Gui Qt5::Widgets + $<$:stdc++fs> ) if (WIN32) diff --git a/src/runtime/res/POC_Runtime.qrc b/src/runtime/res/POC_Runtime.qrc deleted file mode 100644 index d5e87eed..00000000 --- a/src/runtime/res/POC_Runtime.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - icons/run.png - icons/pause.png - - diff --git a/src/runtime/res/icons/pause.png b/src/runtime/res/icons/pause.png deleted file mode 100644 index d7cbb8f8..00000000 Binary files a/src/runtime/res/icons/pause.png and /dev/null differ diff --git a/src/runtime/res/icons/run.png b/src/runtime/res/icons/run.png deleted file mode 100644 index 793697b4..00000000 Binary files a/src/runtime/res/icons/run.png and /dev/null differ diff --git a/src/runtime/src/runtime.cpp b/src/runtime/src/runtime.cpp index 7433fbe1..1490a33d 100644 --- a/src/runtime/src/runtime.cpp +++ b/src/runtime/src/runtime.cpp @@ -20,7 +20,6 @@ int main(int argc, char *argv[]) std::string strConfigurationFilepath = ""; std::string strXODRFilepath = ""; std::string strXOSCFilePath = ""; - bool bAutostart = false; std::cout << std::endl << std::endl; @@ -50,11 +49,6 @@ int main(int argc, char *argv[]) std::cout << "XOSC: " << strXOSCFilePath << std::endl; } } - else if (strcmp(argv[i], "-autostart") == 0) - { - bAutostart = true; - std::cout << "Autostart: true" << std::endl; - } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { ShowHelp(strToolpath); @@ -67,7 +61,7 @@ int main(int argc, char *argv[]) strConfigurationFilepath = argv[1]; QApplication app(argc, argv); - RunConfigGUI(strConfigurationFilepath, strXODRFilepath, strXOSCFilePath, bAutostart, app); + RunConfigGUI(strConfigurationFilepath, strXODRFilepath, strXOSCFilePath, app); return 0; } @@ -82,28 +76,21 @@ void ShowHelp(const std::string &toolPath) std::cout << "\nOpen the application with DefaultXodrConfiguration.xml: \n" << applicationName << " myConfiguration.xml" << std::endl; std::cout << "\nOpen the application with myConfiguration.xml and a given xodr which is under " - "test. Autostart enables the automatic validation mode: \n" - << applicationName << " -config myConfiguration.xml -xodr myTrack.xodr [-autostart]" << std::endl; + "test. \n" + << applicationName << " -config myConfiguration.xml -xodr myTrack.xodr " << std::endl; std::cout << "\nOpen the application with myConfiguration.xml and a given xosc which is under " - "test. Autostart enables the automatic validation mode: \n" - << applicationName << " -config myConfiguration.xml -xosc myTrack.xosc [-autostart]" << std::endl; + "test. \n" + << applicationName << " -config myConfiguration.xml -xosc myTrack.xosc " << std::endl; std::cout << "\n\n"; } void RunConfigGUI(const std::string &strConfigurationFilepath, const std::string &strXODRFilepath, - const std::string &strXOSCFilePath, const bool bAutostart, const QApplication &app) + const std::string &strXOSCFilePath, const QApplication &app) { - cRuntimeWindow mainWindow(strConfigurationFilepath, strXODRFilepath, strXOSCFilePath, bAutostart); + cRuntimeWindow mainWindow(strConfigurationFilepath, strXODRFilepath, strXOSCFilePath); mainWindow.show(); app.processEvents(); - if (bAutostart) - { - mainWindow.Run(); - while (mainWindow.IsRunning()) - app.processEvents(QEventLoop::AllEvents, 200); - } - else - app.exec(); + app.exec(); } diff --git a/src/runtime/src/runtime.h b/src/runtime/src/runtime.h index 6ec38ed1..95b42153 100644 --- a/src/runtime/src/runtime.h +++ b/src/runtime/src/runtime.h @@ -29,4 +29,4 @@ void ShowHelp(const std::string &applicationName); * Runs the config gui */ void RunConfigGUI(const std::string &strConfigurationFilepath, const std::string &strXODRFilepath, - const std::string &strXOSCFilePath, const bool bAutostart, const QApplication &app); + const std::string &strXOSCFilePath, const QApplication &app); diff --git a/src/runtime/src/ui/c_process_log.cpp b/src/runtime/src/ui/c_process_log.cpp deleted file mode 100644 index f4952d58..00000000 --- a/src/runtime/src/ui/c_process_log.cpp +++ /dev/null @@ -1,150 +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/. - */ - -/* - * Copyright 2023 CARIAD SE. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted - * provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions - * and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other materials provided with - * the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used to - * endorse or promote products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY - * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "c_process_log.h" - -#include -#include - -cProcessLog::cProcessLog(QWidget *parent) : QPlainTextEdit(parent) -{ - QFont font; - font.setFamily("Courier"); - font.setFixedPitch(true); - font.setPointSize(10); - - _metrics = new QFontMetrics(font); - - setWordWrapMode(QTextOption::NoWrap); - setFont(font); - setTabStopWidth(2 * _metrics->width(' ')); - setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap); - - _lineNumberArea = new cLineNumberArea(this); - connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(UpdateLineNumberAreaWidth(int))); - connect(this, SIGNAL(updateRequest(QRect, int)), this, SLOT(UpdateLineNumberArea(QRect, int))); - - UpdateLineNumberAreaWidth(3); - setReadOnly(true); -} - -cProcessLog::~cProcessLog() -{ - if (_lineNumberArea != nullptr) - delete _lineNumberArea; - - if (_metrics != nullptr) - delete _metrics; -} - -void cProcessLog::SaveToFile(const QString &filepath) const -{ - QFile file(filepath); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) - return; - - QTextStream out(&file); - out << toPlainText(); - - file.close(); -} - -void cProcessLog::Clear() -{ - clear(); -} - -void cProcessLog::Log(const QString &log) -{ - appendPlainText(log); -} - -void cProcessLog::LineNumberAreaPaintEvent(QPaintEvent *event) -{ - assert(_metrics != nullptr); - assert(_lineNumberArea != nullptr); - - QPainter painter(_lineNumberArea); - painter.fillRect(event->rect(), QColor(240, 240, 240)); - - const int height = _metrics->height(); - const int width = _lineNumberArea->width(); - - painter.setPen(Qt::black); - QTextBlock block = firstVisibleBlock(); - int lineno = 1 + block.blockNumber(); - for (; block.isValid() && block.isVisible(); block = block.next(), ++lineno) - { - auto ypos = static_cast(blockBoundingGeometry(block).translated(contentOffset()).top()); - painter.drawText(0, ypos, _lineNumberArea->width(), height, Qt::AlignRight, QString::number(lineno)); - } -} - -int cProcessLog::LineNumberAreaWidth() const -{ - float no_blocks = static_cast(qMax(1, blockCount())); - int digits = 1 + static_cast(std::log10(no_blocks)); - int space = 3 + _metrics->width('9') * digits; - return qMax(3, space); -} - -void cProcessLog::UpdateLineNumberArea(const QRect &rect, int dy) -{ - assert(_lineNumberArea != nullptr); - - if (dy) - _lineNumberArea->scroll(0, dy); - else - { - _lineNumberArea->update(0, rect.y(), _lineNumberArea->width(), rect.height()); - } - - if (rect.contains(viewport()->rect())) - UpdateLineNumberAreaWidth(0); -} - -void cProcessLog::UpdateLineNumberAreaWidth(int /* newBlockCount */) -{ - setViewportMargins(LineNumberAreaWidth() + 10, 0, 10, 0); -} - -void cProcessLog::resizeEvent(QResizeEvent *event) -{ - assert(_lineNumberArea != nullptr); - - QPlainTextEdit::resizeEvent(event); - - QRect cr = contentsRect(); - _lineNumberArea->setGeometry(QRect(cr.left() + 2, cr.top(), LineNumberAreaWidth() + 2, cr.height())); -} diff --git a/src/runtime/src/ui/c_process_log.h b/src/runtime/src/ui/c_process_log.h deleted file mode 100644 index 5336f514..00000000 --- a/src/runtime/src/ui/c_process_log.h +++ /dev/null @@ -1,102 +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/. - */ - -/* - * Copyright 2023 CARIAD SE. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted - * provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions - * and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other materials provided with - * the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used to - * endorse or promote products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY - * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CPROCESS_LOG_H -#define CPROCESS_LOG_H - -#include -#include -#include -#include - -class cProcessLog : public QPlainTextEdit -{ - Q_OBJECT - - protected: - public: - cProcessLog(QWidget *parent = 0); - virtual ~cProcessLog(); - - // Dumps the console output into a file - void SaveToFile(const QString &filepath) const; - - // Clears the console - void Clear(); - - // Paints the lins number are - void LineNumberAreaPaintEvent(QPaintEvent *event); - - // Returns the width od the line numer area - int LineNumberAreaWidth() const; - - public slots: - void Log(const QString &log); - - void UpdateLineNumberArea(const QRect &rect, int dy); - - void UpdateLineNumberAreaWidth(int); - - protected: - void resizeEvent(QResizeEvent *event) override; - - private: - QWidget *_lineNumberArea{nullptr}; - QFontMetrics *_metrics{nullptr}; -}; - -class cLineNumberArea : public QWidget -{ - public: - cLineNumberArea(cProcessLog *editor) : QWidget(editor), codeEditor(editor) - { - // codeEditor = editor; - } - - QSize sizeHint() const override - { - return QSize(codeEditor->LineNumberAreaWidth(), 0); - } - - protected: - void paintEvent(QPaintEvent *event) override - { - codeEditor->LineNumberAreaPaintEvent(event); - } - - private: - cProcessLog *codeEditor; -}; - -#endif diff --git a/src/runtime/src/ui/c_runtime_control.cpp b/src/runtime/src/ui/c_runtime_control.cpp deleted file mode 100644 index 12b22d7d..00000000 --- a/src/runtime/src/ui/c_runtime_control.cpp +++ /dev/null @@ -1,65 +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 "c_runtime_control.h" - -cRuntimeControl::cRuntimeControl(QWidget *parent) : QWidget(parent) -{ - QHBoxLayout *runtimeLayout = new QHBoxLayout; - runtimeBtn = new QLabel(this); - - runtimeLayout->addWidget(runtimeBtn, 100, Qt::AlignCenter); - - setLayout(runtimeLayout); - - isRunning = false; - UpdateControl(); -} - -void cRuntimeControl::mousePressEvent(QMouseEvent *event) -{ - if (isRunning) - { - emit Abort(); - isRunning = false; - } - else - { - isRunning = true; - emit Run(); - } - - UpdateControl(); -} -void cRuntimeControl::UpdateControl() -{ - if (isRunning) - { - QPixmap pixmap(":/icons/pause.png"); - - runtimeBtn->setPixmap(pixmap); - runtimeBtn->setMask(pixmap.mask()); - } - else - { - QPixmap pixmap(":/icons/run.png"); - - runtimeBtn->setPixmap(pixmap); - runtimeBtn->setMask(pixmap.mask()); - } -} - -bool cRuntimeControl::IsRunning() const -{ - return isRunning; -} - -void cRuntimeControl::FinishedExecution() -{ - isRunning = false; - UpdateControl(); -} diff --git a/src/runtime/src/ui/c_runtime_control.h b/src/runtime/src/ui/c_runtime_control.h deleted file mode 100644 index 9c3280b2..00000000 --- a/src/runtime/src/ui/c_runtime_control.h +++ /dev/null @@ -1,43 +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 CRUNTIME_CONTROL_H -#define CRUNTIME_CONTROL_H - -#include -#include -#include -#include - -class cRuntimeControl : public QWidget -{ - Q_OBJECT - - protected: - QLabel *runtimeBtn; - - public: - cRuntimeControl(QWidget *parent = 0); - - bool IsRunning() const; - signals: - void Abort(); - - void Run(); - - public slots: - void FinishedExecution(); - - protected: - void mousePressEvent(QMouseEvent *event); - - void UpdateControl(); - - bool isRunning; -}; - -#endif diff --git a/src/runtime/src/ui/c_runtime_thread.cpp b/src/runtime/src/ui/c_runtime_thread.cpp deleted file mode 100644 index ccf2b07b..00000000 --- a/src/runtime/src/ui/c_runtime_thread.cpp +++ /dev/null @@ -1,159 +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 "c_runtime_thread.h" - -#include "c_process_log.h" -#include "common/config_format/c_configuration.h" -#include "common/config_format/c_configuration_checker_bundle.h" -#include "common/config_format/c_configuration_report_module.h" - -void cRuntimeThread::Initialize(cProcessLog *const processLog, cConfiguration *const configuration, - const QString &configurationPath) -{ - _abortExecution = false; - _myConfiguration = configuration; - _myConfigurationPath = configurationPath; - _myLog = processLog; -} - -const QString cRuntimeThread::GetApplicationDir() -{ - return QCoreApplication::applicationDirPath() + "/"; -} - -const fs::path cRuntimeThread::GetWorkingDir() -{ - return fs::current_path(); -} - -void cRuntimeThread::Abort() -{ - _abortExecution = true; -} - -bool cRuntimeThread::IsRunning() const -{ - return isRunning(); -} - -void cRuntimeThread::run() -{ - if (nullptr == _myConfiguration) - return; - - emit Log(QString("-------------------------------------------------------------")); - emit Log(QString("---- Cleanup ------------------------------------------------")); - emit Log(QString("-------------------------------------------------------------")); - - for (auto &pFilePath : fs::directory_iterator(GetWorkingDir())) - { - std::string strFileName = pFilePath.path().string(); - GetFileName(&strFileName, false); - - if (StringEndsWith(strFileName, ".xqar")) - { - QString output = QString(" > Delete '%1'.").arg(strFileName.c_str()); - - emit Log(output); - - // Delete file - QFile file(strFileName.c_str()); - file.remove(); - } - } - - emit Log(""); - - // Process CheckerBundles - std::vector checkerBundle = _myConfiguration->GetCheckerBundles(); - std::vector::const_iterator bundleIt = checkerBundle.cbegin(); - - QStringList defaultParams; - defaultParams.append(_myConfigurationPath); - - for (; bundleIt != checkerBundle.cend() && !_abortExecution; bundleIt++) - { - ExecuteProcess(GetApplicationDir() + (*bundleIt)->GetCheckerBundleApplication().c_str(), defaultParams); - } - - // Process ResultPooling - ExecuteProcess(GetApplicationDir() + "ResultPooling.exe", {""}); - - // Process ReportModules - std::vector reportModules = _myConfiguration->GetReportModules(); - std::vector::const_iterator reportModuleIt = reportModules.cbegin(); - - for (; reportModuleIt != reportModules.cend() && !_abortExecution; reportModuleIt++) - { - ExecuteProcess(GetApplicationDir() + (*reportModuleIt)->GetReportModuleApplication().c_str(), defaultParams); - } - - emit Log(""); - emit Log(QString("-------------------------------------------------------------")); - emit Log(QString("---- Finished -----------------------------------------------")); - emit Log(QString("-------------------------------------------------------------")); - - emit Finished(); -} - -int cRuntimeThread::ExecuteProcess(const QString &processName, const QStringList ¶ms) -{ - QProcess process; - - emit Log(QString("-------------------------------------------------------------")); - emit Log(QString("---- Run %1").arg(processName.toLocal8Bit().data())); - emit Log(QString("-------------------------------------------------------------")); - - std::string processExec = processName.toLocal8Bit().data(); - - if (!StringEndsWith(processExec, ".exe")) - processExec = processExec.append(".exe"); - - if (!CheckIfFileExists(processExec)) - { - emit Log(""); - emit Log(QString("Executeable '%1' not found. Abort.").arg(processName.toLocal8Bit().data())); - emit Log(""); - } - - process.start(processName, params); - process.waitForStarted(); - - while (process.state() == QProcess::Running) - { - if (_abortExecution) - { - process.terminate(); - process.waitForFinished(); - - QString stdOut = QString(process.readAllStandardOutput()); - QString stdErr = QString(process.readAllStandardError()); - - if (stdOut.count() > 0) - emit Log(stdOut); - - if (stdErr.count() > 0) - emit Log(stdErr); - - return -1; - } - - process.waitForFinished(1000); - - QString stdOut = QString(process.readAllStandardOutput()); - QString stdErr = QString(process.readAllStandardError()); - - if (stdOut.count() > 0) - emit Log(stdOut); - - if (stdErr.count() > 0) - emit Log(stdErr); - } - - return 0; -} diff --git a/src/runtime/src/ui/c_runtime_thread.h b/src/runtime/src/ui/c_runtime_thread.h deleted file mode 100644 index 3d6da609..00000000 --- a/src/runtime/src/ui/c_runtime_thread.h +++ /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/. - */ -#ifndef CRUNTIME_THREAD_H -#define CRUNTIME_THREAD_H - -#include -#include -#include - -#include "common/qc4openx_filesystem.h" - -class cConfiguration; -class cProcessLog; - -// Implementation of the thread which runs the execution -class cRuntimeThread : public QThread -{ - Q_OBJECT - - public: - void Initialize(cProcessLog *const, cConfiguration *const, const QString &); - - void Abort(); - - bool IsRunning() const; - - /*! - * Executes a Process with a given name and params - * - * \param processName - * \param params - * \return - */ - int ExecuteProcess(const QString &processName, const QStringList ¶ms); - - signals: - void Log(QString log); - - void Finished(); - - protected: - void run(); - - bool _abortExecution{false}; - const cConfiguration *_myConfiguration{nullptr}; - const cProcessLog *_myLog{nullptr}; - QString _myConfigurationPath; - - /** - * Get application directory - * - * @return directory, where the application is installed - */ - const QString GetApplicationDir(); - - /** - * Get working directory - * - * @return directory, from where the application is started - */ - const fs::path GetWorkingDir(); -}; - -#endif diff --git a/src/runtime/src/ui/c_runtime_window.cpp b/src/runtime/src/ui/c_runtime_window.cpp index d0ab268a..5fe8e492 100644 --- a/src/runtime/src/ui/c_runtime_window.cpp +++ b/src/runtime/src/ui/c_runtime_window.cpp @@ -20,18 +20,15 @@ #include "common/result_format/c_result_container.h" #include "../c_configuration_validator.h" -#include "c_process_log.h" #include "c_process_view.h" -#include "c_runtime_control.h" const QString cRuntimeWindow::DEFAULT_XODR_CONFIG = "DefaultXodrConfiguration.xml"; const QString cRuntimeWindow::DEFAULT_XOSC_CONFIG = "DefaultXoscConfiguration.xml"; cRuntimeWindow::cRuntimeWindow(const std::string &strConfigurationFilepath, const std::string &xodrFile, - const std::string &xoscFile, const bool bAutostart, QWidget *parent) + const std::string &xoscFile, QWidget *parent) : QMainWindow(parent) { - _autostart = bAutostart; QAction *newAction = new QAction(tr("&New"), this); newAction->setShortcuts(QKeySequence::New); @@ -52,24 +49,12 @@ cRuntimeWindow::cRuntimeWindow(const std::string &strConfigurationFilepath, cons saveAsAction->setStatusTip(tr("Save configuration")); connect(saveAsAction, &QAction::triggered, this, &cRuntimeWindow::SaveAsConfigurationFile); - QAction *clearConsoleAction = new QAction(tr("Clear"), this); - clearConsoleAction->setStatusTip(tr("Clear console")); - connect(clearConsoleAction, &QAction::triggered, this, &cRuntimeWindow::ClearConsole); - - QAction *saveConsoleAction = new QAction(tr("Save"), this); - saveConsoleAction->setStatusTip(tr("Save console output")); - connect(saveConsoleAction, &QAction::triggered, this, &cRuntimeWindow::SaveConsole); - auto fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(newAction); fileMenu->addAction(openAction); fileMenu->addAction(saveAction); fileMenu->addAction(saveAsAction); - auto consoleMenu = menuBar()->addMenu(tr("&Console")); - consoleMenu->addAction(clearConsoleAction); - consoleMenu->addAction(saveConsoleAction); - QSplitter *splitter = new QSplitter(Qt::Horizontal); QWidget *processWidget = new QWidget(this); @@ -99,24 +84,15 @@ cRuntimeWindow::cRuntimeWindow(const std::string &strConfigurationFilepath, cons _processView->setRootIsDecorated(true); _processView->setHeaderHidden(true); - auto runtimeControl = new cRuntimeControl(this); - processLayout->addWidget(processLabel); processLayout->addWidget(_processView, 2); processLayout->addWidget(processButtonBar, 0); - processLayout->addWidget(runtimeControl, 0); processLayout->setContentsMargins(3, 6, 3, 3); processWidget->setLayout(processLayout); splitter->addWidget(processWidget); QWidget *outputWidget = new QWidget(this); QVBoxLayout *outputLayout = new QVBoxLayout; - QLabel *outputLabel = new QLabel(outputWidget); - outputLabel->setText("Console Output"); - outputLabel->setStyleSheet("font-weight: bold;"); - _processLog = new cProcessLog(this); - outputLayout->addWidget(outputLabel); - outputLayout->addWidget(_processLog); outputLayout->setContentsMargins(3, 6, 3, 3); outputWidget->setLayout(outputLayout); splitter->addWidget(outputWidget); @@ -132,16 +108,6 @@ cRuntimeWindow::cRuntimeWindow(const std::string &strConfigurationFilepath, cons connect(_processView, SIGNAL(ExecuteProcessAndAddConfiguration(QString)), this, SLOT(ExecuteProcessAndAddConfiguration(QString))); - connect(runtimeControl, &cRuntimeControl::Run, this, &cRuntimeWindow::Run); - connect(runtimeControl, &cRuntimeControl::Abort, this, &cRuntimeWindow::Abort); - - connect(&_runningThread, SIGNAL(Log(QString)), _processLog, SLOT(Log(QString))); - connect(this, SIGNAL(Log(QString)), _processLog, SLOT(Log(QString))); - - connect(&_runningThread, SIGNAL(Finished()), runtimeControl, SLOT(FinishedExecution())); - connect(&_runningThread, SIGNAL(Finished()), runtimeControl, SLOT(FinishedExecution())); - connect(this, SIGNAL(Finished()), runtimeControl, SLOT(FinishedExecution())); - // Set the size of the application of the half size of desktop QSize quarterDesktopSize = QDesktopWidget().availableGeometry(this).size() * 0.5f; resize(quarterDesktopSize); @@ -191,6 +157,27 @@ const QString cRuntimeWindow::GetWorkingDir() return QString::fromStdString(fs::current_path().string()); } + +bool cRuntimeWindow::ValidateAndWrite(cConfiguration& configuration, const std::string& filePath){ + std::string message = ""; + if (!cConfigurationValidator::ValidateConfiguration(&configuration, + message)) { + std::stringstream ssDetails; + + ssDetails << "Configuration is invalid." << std::endl << std::endl; + ssDetails << "Message: " << std::endl; + ssDetails << message; + ssDetails << std::endl << std::endl; + ssDetails << "Please fix it before saving configuration file"; + + QMessageBox::warning(this, tr("Error"), tr(ssDetails.str().c_str()), + QMessageBox::Ok); + return false; + } + configuration.WriteConfigurationToFile(filePath); + return true; +} + void cRuntimeWindow::OpenConfigurationFile() { QString filePath = @@ -200,7 +187,7 @@ void cRuntimeWindow::OpenConfigurationFile() ShowConfiguration(&_currentConfiguration); } -bool cRuntimeWindow::SaveConfigurationFile(const bool bAutostart) +bool cRuntimeWindow::SaveConfigurationFile() { if (!_currentConfigurationPath.isEmpty()) { @@ -218,18 +205,18 @@ bool cRuntimeWindow::SaveConfigurationFile(const bool bAutostart) else { QMessageBox::StandardButton reply = QMessageBox::NoButton; - if (!bAutostart) - { - reply = QMessageBox::question(this, "Overwrite Configuration", - "Do you want to overwrite:\n" + fileInfo.fileName(), - QMessageBox::Yes | QMessageBox::No); - } + reply = QMessageBox::question(this, "Overwrite Configuration", + "Do you want to overwrite:\n" + fileInfo.fileName(), + QMessageBox::Yes | QMessageBox::No); - if (bAutostart || reply == QMessageBox::Yes) + if (reply == QMessageBox::Yes) { UpdateConfiguration(); - _currentConfiguration.WriteConfigurationToFile(_currentConfigurationPath.toLocal8Bit().data()); - + bool validation_result = false; + validation_result = ValidateAndWrite(_currentConfiguration, _currentConfigurationPath.toLocal8Bit().data()); + if (!validation_result){ + return false; + } _configurationChanged = false; SetupWindowTitle(); return true; @@ -248,6 +235,7 @@ bool cRuntimeWindow::SaveConfigurationFile(const bool bAutostart) return SaveAsConfigurationFile(); } + bool cRuntimeWindow::SaveAsConfigurationFile() { QString filePath = @@ -273,7 +261,11 @@ bool cRuntimeWindow::SaveAsConfigurationFile() UpdateConfiguration(); _currentConfigurationPath = filePath; - _currentConfiguration.WriteConfigurationToFile(filePath.toLocal8Bit().data()); + bool validation_result = false; + validation_result = ValidateAndWrite(_currentConfiguration, filePath.toLocal8Bit().data()); + if (!validation_result){ + return false; + } _configurationChanged = false; SetupWindowTitle(); @@ -343,7 +335,6 @@ void cRuntimeWindow::CreateNewConfiguration(cConfiguration *const configuration) void cRuntimeWindow::ShowConfiguration(cConfiguration *const configurationToBeShown) { - _processLog->clear(); _processView->LoadConfiguration(configurationToBeShown); @@ -356,26 +347,6 @@ void cRuntimeWindow::NewConfiguration() ShowConfiguration(&_currentConfiguration); } -void cRuntimeWindow::closeEvent(QCloseEvent * /*event*/) -{ - _runningThread.Abort(); - _runningThread.wait(); -} - -void cRuntimeWindow::ClearConsole() -{ - _processLog->Clear(); -} - -void cRuntimeWindow::SaveConsole() -{ - QString filePath = QFileDialog::getSaveFileName(this, tr("Console Dump"), GetWorkingDir(), tr("Log (*.log)")); - - if (!filePath.isEmpty()) - { - _processLog->SaveToFile(filePath); - } -} void cRuntimeWindow::OnChangeConfiguration() { @@ -384,63 +355,6 @@ void cRuntimeWindow::OnChangeConfiguration() SetupWindowTitle(); } -void cRuntimeWindow::Run() -{ - UpdateConfiguration(); - - std::string message = ""; - if (!cConfigurationValidator::ValidateConfiguration(&_currentConfiguration, message)) - { - std::stringstream ssDetails; - - ssDetails << "Configuration is invalid." << std::endl << std::endl; - ssDetails << "Message: " << std::endl; - ssDetails << message; - ssDetails << std::endl << std::endl; - ssDetails << "Please fix. Skip execution."; - - if (!_autostart) - { - QMessageBox::warning(this, tr("Error"), tr(ssDetails.str().c_str()), QMessageBox::Ok); - } - else - std::cerr << ssDetails.str(); - - emit Finished(); - return; - } - - // Save configuration if not saved - bool saved = SaveConfigurationFile(_autostart); - - if (!saved) - { - QMessageBox::warning(this, tr("Error"), tr("Skip execution. Please save the configuration first."), - QMessageBox::Ok); - - emit Finished(); - return; - } - - _processLog->Clear(); - - if (_runningThread.IsRunning()) - _runningThread.Abort(); - - _runningThread.Initialize(_processLog, &_currentConfiguration, _currentConfigurationPath); - - _runningThread.start(); -} - -void cRuntimeWindow::Abort() -{ - _runningThread.Abort(); -} - -bool cRuntimeWindow::IsRunning() const -{ - return _runningThread.IsRunning(); -} int cRuntimeWindow::ExecuteProcessAndAddConfiguration(const QString &processPath) { diff --git a/src/runtime/src/ui/c_runtime_window.h b/src/runtime/src/ui/c_runtime_window.h index f8c908ab..5a72254e 100644 --- a/src/runtime/src/ui/c_runtime_window.h +++ b/src/runtime/src/ui/c_runtime_window.h @@ -10,8 +10,8 @@ #include -#include "c_runtime_thread.h" #include "common/config_format/c_configuration.h" +#include "common/qc4openx_filesystem.h" class cProcessView; class cProcessLog; @@ -24,18 +24,15 @@ class cRuntimeWindow : public QMainWindow protected: cProcessView *_processView{nullptr}; - cProcessLog *_processLog{nullptr}; cConfiguration _currentConfiguration; QString _currentConfigurationPath; - cRuntimeThread _runningThread; bool _configurationChanged{false}; - bool _autostart{true}; public: cRuntimeWindow(const std::string &configurationFilePath, const std::string &xodrFile, const std::string &xoscFile, - const bool bAutostart, QWidget *parent = 0); + QWidget *parent = 0); /* * Loads a configuration from file to datastructure @@ -52,15 +49,6 @@ class cRuntimeWindow : public QMainWindow // Updates the internal configuration void UpdateConfiguration(); - // Returns true if the execution thread is running - bool IsRunning() const; - - public slots: - // Runs the process - void Run(); - - // Aborts the running process - void Abort(); private slots: // Open result file @@ -69,14 +57,10 @@ class cRuntimeWindow : public QMainWindow // SaveAs configuration file bool SaveAsConfigurationFile(); - // Save configuration file - bool SaveConfigurationFile(const bool); + bool ValidateAndWrite(cConfiguration& , const std::string&); - // Saves the console output - void SaveConsole(); - - // Clear the console output - void ClearConsole(); + // Save configuration file + bool SaveConfigurationFile(); // Creates a new Configuration void NewConfiguration(); @@ -118,8 +102,6 @@ class cRuntimeWindow : public QMainWindow */ const QString GetWorkingDir(); - // Handle application close - void closeEvent(QCloseEvent *bar); // Changes the window title of the application void SetupWindowTitle(); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 970c6de4..2168c10a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -26,7 +26,6 @@ if(NOT CMAKE_PROJECT_NAME) endif() include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) - find_package(dev_essential REQUIRED) enable_testing() endif() diff --git a/test/function/CMakeLists.txt b/test/function/CMakeLists.txt index 897bedf1..53d1bd0f 100644 --- a/test/function/CMakeLists.txt +++ b/test/function/CMakeLists.txt @@ -32,7 +32,10 @@ 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 COMMENT "Copying test reference files..." ) diff --git a/test/function/_common/helper.cpp b/test/function/_common/helper.cpp index 8701b899..95becd24 100644 --- a/test/function/_common/helper.cpp +++ b/test/function/_common/helper.cpp @@ -5,9 +5,10 @@ * 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 "helper.h" -qc4openx::Result ExecuteCommand(std::string &strResultMessage, std::string strCommand, const std::string strArgument) +TestResult ExecuteCommand(std::string &strResultMessage, std::string strCommand, const std::string strArgument) { std::string strInstallDir = std::string(QC4OPENX_DBQA_BIN_DIR); strInstallDir.append("/"); @@ -18,7 +19,7 @@ qc4openx::Result ExecuteCommand(std::string &strResultMessage, std::string strCo #endif strTotalCommand.append(strCommand.c_str()); - if (a_util::filesystem::exists(strTotalCommand)) + if (fs::exists(strTotalCommand)) { if (!strArgument.empty()) { @@ -32,67 +33,173 @@ qc4openx::Result ExecuteCommand(std::string &strResultMessage, std::string strCo { strResultMessage = "Command executed with result " + std::to_string(i32Res) + ". Command: '" + strTotalCommand + "'."; - return qc4openx::ERR_FAILED; + return TestResult::ERR_FAILED; } else { - return qc4openx::ERR_NOERROR; + return TestResult::ERR_NOERROR; } } strResultMessage = "Command to execute was not found in any defined install directory. Command: '" + strTotalCommand + "'."; - return qc4openx::ERR_FILE_NOT_FOUND; + return TestResult::ERR_FILE_NOT_FOUND; } -qc4openx::Result CheckFileExists(std::string &strResultMessage, const std::string strFilePath, const bool bDelete) +TestResult CheckFileExists(std::string &strResultMessage, const std::string strFilePath, const bool bDelete) { - if (a_util::filesystem::exists(strFilePath.c_str())) + if (fs::exists(strFilePath.c_str())) { - std::string strFileContent; - a_util::filesystem::readTextFile(strFilePath.c_str(), strFileContent); + // Open the file in input mode + std::ifstream file(strFilePath); + + // Check if the file was successfully opened + if (!file.is_open()) + { + std::cerr << "Failed to open the file: " << strFilePath << std::endl; + return TestResult::ERR_FAILED; + } + + // Read the entire file content into a string + std::ostringstream oss; + oss << file.rdbuf(); + std::string strFileContent = oss.str(); + + // Close the file + file.close(); + if (strFileContent.size() > 0) { if (bDelete == true) { - a_util::filesystem::remove(strFilePath.c_str()); + fs::remove(strFilePath.c_str()); } - return qc4openx::ERR_NOERROR; + return TestResult::ERR_NOERROR; } strResultMessage = "File '" + strFilePath + "' is empty."; - return qc4openx::ERR_UNEXPECTED; + return TestResult::ERR_UNEXPECTED; } strResultMessage = "Could not find file '" + strFilePath + "'."; - return qc4openx::ERR_FILE_NOT_FOUND; + return TestResult::ERR_FILE_NOT_FOUND; } -qc4openx::Result CheckFilesEqual(std::string &strResultMessage, const std::string strFilePath1, - const std::string strFilePath2) +namespace { - FILE *f1 = fopen(strFilePath1.c_str(), "r"); - FILE *f2 = fopen(strFilePath2.c_str(), "r"); - - constexpr int n = 10000; - char buf1[n]; - char buf2[n]; +class SimpleErrorHandler : public xercesc::HandlerBase +{ + public: + void warning(const xercesc::SAXParseException &e) override + { + std::cerr << "Warning: " << xercesc::XMLString::transcode(e.getMessage()) << std::endl; + } + void error(const xercesc::SAXParseException &e) override + { + std::cerr << "Error: " << xercesc::XMLString::transcode(e.getMessage()) << std::endl; + } + void fatalError(const xercesc::SAXParseException &e) override + { + std::cerr << "Fatal Error: " << xercesc::XMLString::transcode(e.getMessage()) << std::endl; + } +}; +} // namespace - while (!feof(f1) || !feof(f2)) +TestResult ValidateXmlSchema(const std::string &xmlFile, const std::string &xsdFile) +{ + try + { + xercesc::XMLPlatformUtils::Initialize(); + } + catch (const xercesc::XMLException &e) { - size_t r1 = fread(buf1, 1, n, f1); - size_t r2 = fread(buf2, 1, n, f2); + std::cerr << "Error during initialization! :\n" << xercesc::XMLString::transcode(e.getMessage()) << std::endl; + return TestResult::ERR_FAILED; + } - if (r1 != r2 || memcmp(buf1, buf2, r1)) + // Read and print the XML file + std::ifstream xmlStream(xmlFile); + if (xmlStream.is_open()) + { + std::cout << "Beginning of XML file: " << std::endl; + for (int i = 0; !xmlStream.eof(); ++i) { - fclose(f1); - fclose(f2); - strResultMessage = "Files '" + strFilePath1 + "' and '" + strFilePath2 + "' do not match."; - return qc4openx::ERR_FAILED; + std::string line; + std::getline(xmlStream, line); + std::cout << line << std::endl; } + xmlStream.close(); } + else + { + std::cerr << "Failed to open XML file: " << xmlFile << std::endl; + return TestResult::ERR_FILE_NOT_FOUND; + } + + xercesc::XercesDOMParser parser; + parser.setExternalNoNamespaceSchemaLocation(xsdFile.c_str()); + parser.setExitOnFirstFatalError(true); + parser.setValidationConstraintFatal(true); + parser.setValidationScheme(xercesc::XercesDOMParser::Val_Auto); + parser.setDoNamespaces(true); + parser.setDoSchema(true); - fclose(f1); - fclose(f2); - return qc4openx::ERR_NOERROR; + SimpleErrorHandler errorHandler; + parser.setErrorHandler(&errorHandler); + + parser.parse(xmlFile.c_str()); + + // Check error handler state + if (parser.getErrorCount() > 0) + { + // If error handler recorded errors, return ERR_FAILED + return TestResult::ERR_FAILED; + } + return TestResult::ERR_NOERROR; +} + +TestResult XmlContainsNode(const std::string &xmlFile, const std::string &nodeName) +{ + try + { + xercesc::XMLPlatformUtils::Initialize(); + } + catch (const xercesc::XMLException &e) + { + std::cerr << "Error during initialization! :\n" << xercesc::XMLString::transcode(e.getMessage()) << std::endl; + return TestResult::ERR_FAILED; + } + + xercesc::XercesDOMParser parser; + parser.setValidationScheme(xercesc::XercesDOMParser::Val_Never); + parser.setDoNamespaces(false); + parser.setDoSchema(false); + parser.parse(xmlFile.c_str()); + + // Get the DOM document + xercesc::DOMDocument *doc = parser.getDocument(); + if (!doc) + { + std::cerr << "Unable to get DOMDocument object " << std::endl; + xercesc::XMLPlatformUtils::Terminate(); + return TestResult::ERR_FILE_NOT_FOUND; + } + + // Convert nodeName to XMLCh* + XMLCh *xmlNodeName = xercesc::XMLString::transcode(nodeName.c_str()); + + // Find the node + xercesc::DOMNodeList *nodes = doc->getElementsByTagName(xmlNodeName); + xercesc::XMLString::release(&xmlNodeName); + + if (nodes->getLength() > 0) + { + xercesc::XMLPlatformUtils::Terminate(); + 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 b20afafe..7b6edd31 100644 --- a/test/function/_common/helper.h +++ b/test/function/_common/helper.h @@ -9,12 +9,28 @@ #define _HELPER_HEADER_ #include - -#include "a_util/filesystem.h" -#include "a_util/result.h" +#include "qc4openx_filesystem.h" #include "gtest/gtest.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "qc4openx_errors.h" +// Define ANSI color codes +#define COLOR_GREEN "\033[32m" +#define COLOR_YELLOW "\033[33m" +#define COLOR_RESET "\033[0m" /** * This macro prints a formatted message during test execution. @@ -23,9 +39,7 @@ */ #define GTEST_PRINTF(_message) \ { \ - testing::internal::ColoredPrintf(testing::internal::COLOR_GREEN, "[ ] "); \ - testing::internal::ColoredPrintf(testing::internal::COLOR_YELLOW, _message); \ - testing::internal::ColoredPrintf(testing::internal::COLOR_YELLOW, "\n"); \ + std::cout << COLOR_GREEN << "[ ] " << COLOR_YELLOW << _message << COLOR_YELLOW << "\n" << COLOR_RESET; \ } /** @@ -41,13 +55,29 @@ } \ ASSERT_TRUE(expression) -qc4openx::Result ExecuteCommand(std::string &strResultMessage, std::string strCommand, - const std::string strArgument = ""); +enum class TestResult +{ + ERR_NOERROR, + ERR_UNKNOWN, + ERR_UNEXPECTED, + ERR_UNKNOWN_FORMAT, + ERR_FILE_NOT_FOUND, + ERR_FAILED, +}; + +// Overload the |= operator +inline TestResult &operator|=(TestResult &lhs, const TestResult &rhs) +{ + lhs = static_cast(static_cast::type>(lhs) | + static_cast::type>(rhs)); + return lhs; +} + +TestResult ExecuteCommand(std::string &strResultMessage, std::string strCommand, const std::string strArgument = ""); -qc4openx::Result CheckFileExists(std::string &strResultMessage, const std::string strFilePath, - const bool bDelete = true); +TestResult CheckFileExists(std::string &strResultMessage, const std::string strFilePath, const bool bDelete = true); -qc4openx::Result CheckFilesEqual(std::string &strResultMessage, const std::string strFilePath1, - const std::string strFilePath2); +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/_common/qc4openx_filesystem.h b/test/function/_common/qc4openx_filesystem.h new file mode 100644 index 00000000..f82be48d --- /dev/null +++ b/test/function/_common/qc4openx_filesystem.h @@ -0,0 +1,24 @@ +/** + * 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 QC4OPENX_FILESYSTEM_H_ +#define QC4OPENX_FILESYSTEM_H_ + +#ifdef __has_include +#if __has_include() +#include +namespace fs = std::filesystem; +#else +#include +namespace fs = std::experimental::filesystem; +#endif +#else +#error __has_include is not defined, but is needed to detect correct filesystem! +#endif + +#endif diff --git a/test/function/examples/example_checker_bundle/src/CMakeLists.txt b/test/function/examples/example_checker_bundle/src/CMakeLists.txt index ec0d57f5..3248b889 100644 --- a/test/function/examples/example_checker_bundle/src/CMakeLists.txt +++ b/test/function/examples/example_checker_bundle/src/CMakeLists.txt @@ -9,8 +9,11 @@ set(TEST_NAME example_checker_bundle_tester) set_property(GLOBAL PROPERTY USE_FOLDERS true) +find_package(XercesC REQUIRED) + include_directories(${TEST_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/../../../_common) + ${CMAKE_CURRENT_SOURCE_DIR}/../../../_common + ${XercesC_INCLUDE_DIRS}) add_executable(${TEST_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../../../_common/helper.cpp @@ -24,8 +27,8 @@ add_test(NAME ${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE GTest::gtest_main - dev_essential::result - dev_essential::system + $<$:stdc++fs> + ${XercesC_LIBRARIES} ) target_compile_definitions(${TEST_NAME} 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 3cb5bcbe..a91bde75 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 @@ -23,8 +23,8 @@ TEST_F(cTesterExampleCheckerBundle, CmdBasic) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); } TEST_F(cTesterExampleCheckerBundle, CmdDefaultConfig) @@ -33,11 +33,11 @@ TEST_F(cTesterExampleCheckerBundle, CmdDefaultConfig) std::string strDefaultConfigFilePath = strWorkingDir + "/" + std::string(MODULE_NAME) + ".xqar"; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "--defaultconfig"); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "--defaultconfig"); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= CheckFileExists(strResultMessage, strDefaultConfigFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); } TEST_F(cTesterExampleCheckerBundle, CmdConfig) @@ -46,18 +46,35 @@ TEST_F(cTesterExampleCheckerBundle, CmdConfig) std::string strConfigFilePath = strTestFilesDir + "/" + std::string(MODULE_NAME) + "_config.xml"; std::string strResultFilePath = strWorkingDir + "/" + std::string(MODULE_NAME) + ".xqar"; - std::string strExpectedResultFilePath = strTestFilesDir + "/" + std::string(MODULE_NAME) + ".xqar"; + std::string strXsdFilePath = strTestFilesDir + "/../../../doc/schema/xqar_report_format.xsd"; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, strConfigFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + 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 |= ValidateXmlSchema(strResultFilePath, strXsdFilePath); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); + + fs::remove(strResultFilePath.c_str()); +} + +TEST_F(cTesterExampleCheckerBundle, CmdConfigContainsIssue) +{ + 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 == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); - nRes |= CheckFilesEqual(strResultMessage, strResultFilePath, strExpectedResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + nRes |= XmlContainsNode(strResultFilePath, "Issue"); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); - a_util::filesystem::remove(strResultFilePath.c_str()); + fs::remove(strResultFilePath.c_str()); } TEST_F(cTesterExampleCheckerBundle, CmdXodr) @@ -66,40 +83,40 @@ TEST_F(cTesterExampleCheckerBundle, CmdXodr) std::string strXodrFilePath = "../stimuli/xodr_examples/three_connected_roads_with_steps.xodr"; std::string strResultFilePath = strWorkingDir + "/" + std::string(MODULE_NAME) + ".xqar"; - std::string strExpectedResultFilePath = strTestFilesDir + "/" + std::string(MODULE_NAME) + ".xqar"; + std::string strXsdFilePath = strTestFilesDir + "/../../../doc/schema/xqar_report_format.xsd"; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, strXodrFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, strXodrFilePath); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= CheckFileExists(strResultMessage, strResultFilePath, false); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); - nRes |= CheckFilesEqual(strResultMessage, strResultFilePath, strExpectedResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + nRes |= ValidateXmlSchema(strResultFilePath, strXsdFilePath); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); - a_util::filesystem::remove(strResultFilePath.c_str()); + fs::remove(strResultFilePath.c_str()); } TEST_F(cTesterExampleCheckerBundle, CmdConfigFileNotFound) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error.xml"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error.xml"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } TEST_F(cTesterExampleCheckerBundle, CmdFirstArgumentWrong) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } TEST_F(cTesterExampleCheckerBundle, CmdTooMuchArguments) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "a b"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "a b"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } diff --git a/test/function/report_modules/report_module_gui/src/CMakeLists.txt b/test/function/report_modules/report_module_gui/src/CMakeLists.txt index a267f658..0a9e129f 100644 --- a/test/function/report_modules/report_module_gui/src/CMakeLists.txt +++ b/test/function/report_modules/report_module_gui/src/CMakeLists.txt @@ -9,8 +9,11 @@ set(TEST_NAME report_module_gui_tester) set_property(GLOBAL PROPERTY USE_FOLDERS true) +find_package(XercesC REQUIRED) + include_directories(${TEST_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/../../../_common) + ${CMAKE_CURRENT_SOURCE_DIR}/../../../_common + ${XercesC_INCLUDE_DIRS}) add_executable(${TEST_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../../../_common/helper.cpp @@ -24,11 +27,10 @@ add_test(NAME ${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE GTest::gtest_main - dev_essential::result - dev_essential::system $<$:dl> $<$:pthread> $<$:stdc++fs> + ${XercesC_LIBRARIES} ) target_compile_definitions(${TEST_NAME} PRIVATE QC4OPENX_DBQA_BIN_DIR="${QC4OPENX_DBQA_DIR}/bin") diff --git a/test/function/report_modules/report_module_gui/src/report_module_gui_tester.cpp b/test/function/report_modules/report_module_gui/src/report_module_gui_tester.cpp index 68841e6d..7ea02485 100644 --- a/test/function/report_modules/report_module_gui/src/report_module_gui_tester.cpp +++ b/test/function/report_modules/report_module_gui/src/report_module_gui_tester.cpp @@ -19,25 +19,24 @@ TEST_F(cTesterReportModuleGui, CmdHelp) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "-h"); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "-h"); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= ExecuteCommand(strResultMessage, MODULE_NAME, "--help"); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); } TEST_F(cTesterReportModuleGui, CmdDefaultConfig) { std::string strResultMessage; - std::string strDefaultConfigFilePath = - a_util::filesystem::getWorkingDirectory().toString() + "/" + std::string(MODULE_NAME) + ".xml"; + std::string strDefaultConfigFilePath = fs::current_path().string() + "/" + std::string(MODULE_NAME) + ".xml"; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "--defaultconfig"); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "--defaultconfig"); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= CheckFileExists(strResultMessage, strDefaultConfigFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); } TEST_F(cTesterReportModuleGui, CmdConfig) @@ -54,30 +53,30 @@ TEST_F(cTesterReportModuleGui, CmdConfigFileNotFound) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error.xml"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error.xml"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } TEST_F(cTesterReportModuleGui, CmdXqarFileNotFound) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error.xqar"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error.xqar"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } TEST_F(cTesterReportModuleGui, CmdFirstArgumentWrong) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } TEST_F(cTesterReportModuleGui, CmdTooMuchArguments) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "a b"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "a b"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } diff --git a/test/function/report_modules/report_module_text/src/CMakeLists.txt b/test/function/report_modules/report_module_text/src/CMakeLists.txt index ea2eda87..ab0f3006 100644 --- a/test/function/report_modules/report_module_text/src/CMakeLists.txt +++ b/test/function/report_modules/report_module_text/src/CMakeLists.txt @@ -7,8 +7,11 @@ set(TEST_NAME report_module_text_tester) +find_package(XercesC REQUIRED) + include_directories(${TEST_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/../../../_common) + ${CMAKE_CURRENT_SOURCE_DIR}/../../../_common + ${XercesC_INCLUDE_DIRS}) add_executable(${TEST_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../../../_common/helper.cpp @@ -22,8 +25,8 @@ add_test(NAME ${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE GTest::gtest_main - dev_essential::result - dev_essential::system + $<$:stdc++fs> + ${XercesC_LIBRARIES} ) target_compile_definitions(${TEST_NAME} diff --git a/test/function/report_modules/report_module_text/src/report_module_text_tester.cpp b/test/function/report_modules/report_module_text/src/report_module_text_tester.cpp index 9f68727c..a214740a 100644 --- a/test/function/report_modules/report_module_text/src/report_module_text_tester.cpp +++ b/test/function/report_modules/report_module_text/src/report_module_text_tester.cpp @@ -23,8 +23,8 @@ TEST_F(cTesterReportModuleText, CmdBasic) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); } TEST_F(cTesterReportModuleText, CmdDefaultConfig) @@ -33,11 +33,11 @@ TEST_F(cTesterReportModuleText, CmdDefaultConfig) std::string strDefaultConfigFilePath = strWorkingDir + "/" + std::string(MODULE_NAME) + ".xml"; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "--defaultconfig"); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "--defaultconfig"); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= CheckFileExists(strResultMessage, strDefaultConfigFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); } TEST_F(cTesterReportModuleText, CmdConfig) @@ -47,11 +47,11 @@ TEST_F(cTesterReportModuleText, CmdConfig) std::string strConfigFilePath = strTestFilesDir + "/" + std::string(MODULE_NAME) + "_config.xml"; std::string strReportFilePath = strWorkingDir + "/" + "Report.txt"; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, strConfigFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, strConfigFilePath); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= CheckFileExists(strResultMessage, strReportFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); } TEST_F(cTesterReportModuleText, CmdXqar) @@ -61,41 +61,41 @@ TEST_F(cTesterReportModuleText, CmdXqar) std::string strResultFilePath = strTestFilesDir + "/" + "Result.xqar"; std::string strReportFilePath = strWorkingDir + "/" + "Report.txt"; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, strResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, strResultFilePath); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= CheckFileExists(strResultMessage, strReportFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); } TEST_F(cTesterReportModuleText, CmdConfigFileNotFound) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error.xml"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error.xml"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } TEST_F(cTesterReportModuleText, CmdXqarFileNotFound) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error.xqar"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error.xqar"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } TEST_F(cTesterReportModuleText, CmdFirstArgumentWrong) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "error"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } TEST_F(cTesterReportModuleText, CmdTooMuchArguments) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "a b"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "a b"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } diff --git a/test/function/result_pooling/src/CMakeLists.txt b/test/function/result_pooling/src/CMakeLists.txt index 1c2e7365..74235f94 100644 --- a/test/function/result_pooling/src/CMakeLists.txt +++ b/test/function/result_pooling/src/CMakeLists.txt @@ -9,8 +9,11 @@ set(TEST_NAME result_pooling_tester) set_property(GLOBAL PROPERTY USE_FOLDERS true) +find_package(XercesC REQUIRED) + include_directories(${TEST_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/../../_common) + ${CMAKE_CURRENT_SOURCE_DIR}/../../_common + ${XercesC_INCLUDE_DIRS}) add_executable(${TEST_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../../_common/helper.cpp @@ -24,8 +27,8 @@ add_test(NAME ${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE GTest::gtest_main - dev_essential::result - dev_essential::system + $<$:stdc++fs> + ${XercesC_LIBRARIES} ) target_compile_definitions(${TEST_NAME} diff --git a/test/function/result_pooling/src/result_pooling_tester.cpp b/test/function/result_pooling/src/result_pooling_tester.cpp index c4618a20..1836f75e 100644 --- a/test/function/result_pooling/src/result_pooling_tester.cpp +++ b/test/function/result_pooling/src/result_pooling_tester.cpp @@ -24,18 +24,18 @@ TEST_F(cTesterResultPooling, CmdBasic) std::string strResultMessage; std::string strResultFilePath = strWorkingDir + "/" + "Result.xqar"; - std::string strExpectedResultFilePath = strTestFilesDir + "/" + "EmptyResult.xqar"; + std::string strXsdFilePath = strTestFilesDir + "/../../doc/schema/xqar_report_format.xsd"; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= CheckFileExists(strResultMessage, strResultFilePath, false); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); - nRes |= CheckFilesEqual(strResultMessage, strResultFilePath, strExpectedResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + nRes |= ValidateXmlSchema(strResultFilePath, strXsdFilePath); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); - a_util::filesystem::remove(strResultFilePath.c_str()); + fs::remove(strResultFilePath.c_str()); } TEST_F(cTesterResultPooling, CmdDir) @@ -45,11 +45,11 @@ TEST_F(cTesterResultPooling, CmdDir) std::string strResultFilePath = strWorkingDir + "/" + "Result.xqar"; std::string strExpectedResultFilePath = strTestFilesDir + "/" + "Result.xqar"; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, strTestFilesDir); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, strTestFilesDir); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= CheckFileExists(strResultMessage, strResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); // Result.xqar has timestamps and no explicit order --> no simple check for files equality possible } @@ -59,32 +59,32 @@ TEST_F(cTesterResultPooling, CmdDirNoResults) std::string strResultMessage; std::string strResultFilePath = strWorkingDir + "/" + "Result.xqar"; - std::string strExpectedResultFilePath = strTestFilesDir + "/" + "EmptyResult.xqar"; + std::string strXsdFilePath = strTestFilesDir + "/../../doc/schema/xqar_report_format.xsd"; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, ".."); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, ".."); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= CheckFileExists(strResultMessage, strResultFilePath, false); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); - nRes |= CheckFilesEqual(strResultMessage, strResultFilePath, strExpectedResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + nRes |= ValidateXmlSchema(strResultFilePath, strXsdFilePath); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); - a_util::filesystem::remove(strResultFilePath.c_str()); + fs::remove(strResultFilePath.c_str()); } TEST_F(cTesterResultPooling, CmdDirNotValid) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "./error/"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "./error/"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } TEST_F(cTesterResultPooling, CmdTooMuchArguments) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "a b"); - ASSERT_TRUE(nRes == qc4openx::ERR_FAILED); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "a b"); + ASSERT_TRUE(nRes == TestResult::ERR_FAILED); } diff --git a/test/function/runtime/src/CMakeLists.txt b/test/function/runtime/src/CMakeLists.txt index 6fe252b9..e2056d58 100644 --- a/test/function/runtime/src/CMakeLists.txt +++ b/test/function/runtime/src/CMakeLists.txt @@ -9,8 +9,11 @@ set(TEST_NAME runtime_tester) set_property(GLOBAL PROPERTY USE_FOLDERS true) +find_package(XercesC REQUIRED) + include_directories(${TEST_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/../../_common) + ${CMAKE_CURRENT_SOURCE_DIR}/../../_common + ${XercesC_INCLUDE_DIRS}) add_executable(${TEST_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../../_common/helper.cpp @@ -24,10 +27,9 @@ add_test(NAME ${TEST_NAME} target_link_libraries(${TEST_NAME} PRIVATE GTest::gtest_main - dev_essential::result - dev_essential::system $<$:pthread> $<$:stdc++fs> + ${XercesC_LIBRARIES} ) target_compile_definitions(${TEST_NAME} @@ -35,4 +37,4 @@ target_compile_definitions(${TEST_NAME} PRIVATE QC4OPENX_DBQA_RUNTIME_TEST_WORK_DIR="${CMAKE_CURRENT_BINARY_DIR}/../.." PRIVATE QC4OPENX_DBQA_RUNTIME_TEST_REF_DIR="${REFERENCE_FILES_INSTALL_DIR}/function/runtime") -set_target_properties(${TEST_NAME} PROPERTIES FOLDER test/function) \ No newline at end of file +set_target_properties(${TEST_NAME} PROPERTIES FOLDER test/function) diff --git a/test/function/runtime/src/runtime_tester.cpp b/test/function/runtime/src/runtime_tester.cpp index 26843465..7c2fd7f8 100644 --- a/test/function/runtime/src/runtime_tester.cpp +++ b/test/function/runtime/src/runtime_tester.cpp @@ -23,71 +23,10 @@ TEST_F(cTesterRuntime, CmdHelp) { std::string strResultMessage; - qc4openx::Result nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "-h"); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + TestResult nRes = ExecuteCommand(strResultMessage, MODULE_NAME, "-h"); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); nRes |= ExecuteCommand(strResultMessage, MODULE_NAME, "--help"); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); + ASSERT_TRUE_EXT(nRes == TestResult::ERR_NOERROR, strResultMessage.c_str()); } -TEST_F(cTesterRuntime, CmdConfig) -{ - // Implicit tested with PCB Test dbqa_roundtrip test_config_gui -} - -TEST_F(cTesterRuntime, CmdConfigAutostart) -{ - std::string strResultMessage; - - std::string strConfigFilePath = strTestFilesDir + "/" + "DemoCheckerBundle_config.xml"; - std::string strResultFilePath = strWorkingDir + "/" + "Result.xqar"; - - qc4openx::Result nRes = - ExecuteCommand(strResultMessage, MODULE_NAME, "-config " + strConfigFilePath + " -autostart"); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); - - // DemoCheckerBundle not found in bin (is in examples) --> no DemoCheckerBundle.xqar --> Result.xqar with no entries - - nRes |= CheckFileExists(strResultMessage, strResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); -} - -TEST_F(cTesterRuntime, CmdConfigXodrAutostart) -{ - std::string strResultMessage; - - std::string strConfigFilePath = strTestFilesDir + "/" + "XodrSchemaChecker_config.xml"; - std::string strXodrFilePath = "../stimuli/xodr_examples/three_connected_roads_with_steps.xodr"; - std::string strXodrSchemaCheckerResultFilePath = strWorkingDir + "/" + "XodrSchemaChecker.xqar"; - std::string strResultFilePath = strWorkingDir + "/" + "Result.xqar"; - - qc4openx::Result nRes = ExecuteCommand( - strResultMessage, MODULE_NAME, "-config " + strConfigFilePath + " -xodr " + strXodrFilePath + " -autostart"); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); - - nRes |= CheckFileExists(strResultMessage, strXodrSchemaCheckerResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); - - nRes |= CheckFileExists(strResultMessage, strResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); -} - -TEST_F(cTesterRuntime, CmdConfigXoscAutostart) -{ - std::string strResultMessage; - - std::string strConfigFilePath = strTestFilesDir + "/" + "XoscSchemaChecker_config.xml"; - std::string strXoscFilePath = "../stimuli/xosc_examples/Einscherer_with_errors.xosc"; - std::string strXoscSchemaCheckerResultFilePath = strWorkingDir + "/" + "XoscSchemaChecker.xqar"; - std::string strResultFilePath = strWorkingDir + "/" + "Result.xqar"; - - qc4openx::Result nRes = ExecuteCommand( - strResultMessage, MODULE_NAME, "-config " + strConfigFilePath + " -xosc " + strXoscFilePath + " -autostart"); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); - - nRes |= CheckFileExists(strResultMessage, strXoscSchemaCheckerResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); - - nRes |= CheckFileExists(strResultMessage, strResultFilePath); - ASSERT_TRUE_EXT(nRes == qc4openx::ERR_NOERROR, strResultMessage.c_str()); -}