From 264b7dab06a9547a4842bdb4f1bd3df19e6b528a Mon Sep 17 00:00:00 2001 From: ClemensLinnhoff Date: Wed, 26 Jun 2024 14:09:20 +0200 Subject: [PATCH 1/4] Update pipeline Signed-off-by: ClemensLinnhoff --- .github/workflows/build.yml | 6 +- .github/workflows/build_esmini.yml | 2 +- .github/workflows/build_openmcx.yml | 2 +- .github/workflows/build_osi-validation.yml | 55 +++++ .github/workflows/build_osi_field_checker.yml | 79 ------- .github/workflows/build_tracefile_player.yml | 4 +- .github/workflows/build_tracefile_writer.yml | 4 +- .github/workflows/cl0.yml | 2 +- .github/workflows/cl2.yml | 106 ++++++--- .github/workflows/cl3.yml | 211 ++++++++++++++++++ .github/workflows/cpp-linter.yml | 4 +- .github/workflows/credibility_assessment.yml | 5 + .github/workflows/fmu_artifact.yml | 4 +- .github/workflows/fmu_checker.yml | 28 ++- .github/workflows/markdown.yml | 2 +- .github/workflows/unit-tests.yml | 6 +- 16 files changed, 392 insertions(+), 128 deletions(-) create mode 100644 .github/workflows/build_osi-validation.yml delete mode 100644 .github/workflows/build_osi_field_checker.yml create mode 100644 .github/workflows/cl3.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index adb7b22..54531b4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,13 +10,13 @@ jobs: steps: - name: Checkout Model - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Cache Protobuf id: cache-protobuf - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: protobuf-21.12 key: ${{ runner.os }}-protobuf @@ -55,7 +55,7 @@ jobs: - name: Cache Model FMU id: cache-model-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/model_fmu key: ${{ runner.os }}-model-fmu-${{ github.sha }} diff --git a/.github/workflows/build_esmini.yml b/.github/workflows/build_esmini.yml index f6af496..6774eef 100644 --- a/.github/workflows/build_esmini.yml +++ b/.github/workflows/build_esmini.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Cache esmini FMU id: cache-esmini-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/esmini_fmu key: ${{ runner.os }}-esmini-fmu diff --git a/.github/workflows/build_openmcx.yml b/.github/workflows/build_openmcx.yml index 14d98c6..8280c83 100644 --- a/.github/workflows/build_openmcx.yml +++ b/.github/workflows/build_openmcx.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Cache OpenMCx id: cache-openmcx - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: openmcx key: ${{ runner.os }}-openmcx diff --git a/.github/workflows/build_osi-validation.yml b/.github/workflows/build_osi-validation.yml new file mode 100644 index 0000000..eee4c75 --- /dev/null +++ b/.github/workflows/build_osi-validation.yml @@ -0,0 +1,55 @@ +name: Build osi-validation + +on: + workflow_call: + +jobs: + build_esmini: + name: Build osi-validation + runs-on: ubuntu-latest + + steps: + - name: Cache osi-validation + id: cache-osi-validation + uses: actions/cache@v4 + with: + path: /tmp/osi-validation + key: ${{ runner.os }}-osi-validation + + - name: Get osi-validation + if: steps.cache-osi-validation.outputs.cache-hit != 'true' + working-directory: /tmp + env: + GIT_CLONE_PROTECTION_ACTIVE: false + run: git clone https://github.com/OpenSimulationInterface/osi-validation.git + + - name: Update Submodules + if: steps.cache-osi-validation.outputs.cache-hit != 'true' + working-directory: /tmp/osi-validation + run: git submodule update --init + + - name: Build osi-validation + if: steps.cache-osi-validation.outputs.cache-hit != 'true' + working-directory: /tmp/osi-validation + run: | + python3 -m venv .venv + source .venv/bin/activate + python3 -m pip install --upgrade pip + python3 -m pip install -r requirements_develop.txt + cd open-simulation-interface && python3 -m pip install . && cd .. + python3 -m pip install -r requirements.txt + python3 rules2yml.py -d rules + python3 -m pip install . + + - name: Generate default rules + if: steps.cache-osi-validation.outputs.cache-hit != 'true' + working-directory: /tmp/osi-validation + run: | + source .venv/bin/activate + python3 rules2yml.py + + - name: Add Commit ID to Cache + if: steps.cache-osi-validation.outputs.cache-hit != 'true' + working-directory: /tmp/osi-validation + run: | + git rev-parse --short HEAD > commit-id.txt diff --git a/.github/workflows/build_osi_field_checker.yml b/.github/workflows/build_osi_field_checker.yml deleted file mode 100644 index 9aff895..0000000 --- a/.github/workflows/build_osi_field_checker.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: Build OSI Field Checker - -on: - workflow_call: - -jobs: - build_osi_field_checker_fmu: - name: Build OSI Field Checker - runs-on: ubuntu-latest - - steps: - - name: Cache Protobuf - id: cache-protobuf - uses: actions/cache@v3 - with: - path: protobuf-21.12 - key: ${{ runner.os }}-protobuf - - - name: Download ProtoBuf - if: steps.cache-protobuf.outputs.cache-hit != 'true' - run: curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protobuf-all-21.12.tar.gz && tar xzvf protobuf-all-21.12.tar.gz - - - name: Build ProtoBuf - if: steps.cache-protobuf.outputs.cache-hit != 'true' - working-directory: protobuf-21.12 - run: ./configure DIST_LANG=cpp --disable-shared CXXFLAGS="-fPIC" && make -j4 - - - name: Install ProtoBuf - working-directory: protobuf-21.12 - run: sudo make install && sudo ldconfig - - - name: Cache OSI Field Checker FMU - id: cache-osi-field-checker - uses: actions/cache@v3 - with: - path: /tmp/osi-field-checker - key: ${{ runner.os }}-osi-field-checker - - - name: Clone OpenMSL OSI Field Checker - if: steps.cache-osi-field-checker.outputs.cache-hit != 'true' - run: git clone https://github.com/openMSL/sl-5-2-osi-field-checker.git - - - name: Prepare C++ Build - if: steps.cache-osi-field-checker.outputs.cache-hit != 'true' - working-directory: sl-5-2-osi-field-checker - run: git submodule update --init && mkdir build - - - name: Configure CMake - if: steps.cache-osi-field-checker.outputs.cache-hit != 'true' - working-directory: sl-5-2-osi-field-checker/build - run: cmake -DCMAKE_PREFIX_PATH:PATH=${DEPS_DIR}/protobuf/install .. - - - name: Build C++ - if: steps.cache-osi-field-checker.outputs.cache-hit != 'true' - working-directory: sl-5-2-osi-field-checker/build - run: cmake --build . -j4 - - - name: Create FMU Directory - if: steps.cache-osi-field-checker.outputs.cache-hit != 'true' - working-directory: sl-5-2-osi-field-checker/build - run: mkdir /tmp/osi-field-checker - - - name: Copy Commit ID to Cache - if: steps.cache-osi-field-checker.outputs.cache-hit != 'true' - working-directory: sl-5-2-osi-field-checker - run: | - git rev-parse --short HEAD > commit-id.txt - cp commit-id.txt /tmp/osi-field-checker/commit-id.txt - - - name: Copy OSI Field Checker FMU - if: steps.cache-osi-field-checker.outputs.cache-hit != 'true' - working-directory: sl-5-2-osi-field-checker/build - run: cp OSIFieldChecker.fmu /tmp/osi-field-checker/OSIFieldChecker.fmu - - - name: Commit ID - working-directory: /tmp/osi-field-checker - run: | - echo "Commit ID: " - echo $(cat commit-id.txt) diff --git a/.github/workflows/build_tracefile_player.yml b/.github/workflows/build_tracefile_player.yml index b07a6c7..ad34aac 100644 --- a/.github/workflows/build_tracefile_player.yml +++ b/.github/workflows/build_tracefile_player.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Cache Protobuf id: cache-protobuf - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: protobuf-21.12 key: ${{ runner.os }}-protobuf @@ -31,7 +31,7 @@ jobs: - name: Cache Tracefile Player FMU id: cache-tracefile-player-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/tracefile_player_fmu key: ${{ runner.os }}-tracefile-player-fmu diff --git a/.github/workflows/build_tracefile_writer.yml b/.github/workflows/build_tracefile_writer.yml index ea64ddd..4709029 100644 --- a/.github/workflows/build_tracefile_writer.yml +++ b/.github/workflows/build_tracefile_writer.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Cache Protobuf id: cache-protobuf - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: protobuf-21.12 key: ${{ runner.os }}-protobuf @@ -31,7 +31,7 @@ jobs: - name: Cache Tracefile Writer FMU id: cache-tracefile-writer-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/tracefile_writer_fmu key: ${{ runner.os }}-tracefile-writer-fmu diff --git a/.github/workflows/cl0.yml b/.github/workflows/cl0.yml index 2a62985..8a2d8ab 100644 --- a/.github/workflows/cl0.yml +++ b/.github/workflows/cl0.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: enarx/spdx@master with: licenses: Apache-2.0 BSD-3-Clause BSD-2-Clause MIT MPL-2.0 diff --git a/.github/workflows/cl2.yml b/.github/workflows/cl2.yml index 8d2e8b8..3092087 100644 --- a/.github/workflows/cl2.yml +++ b/.github/workflows/cl2.yml @@ -16,9 +16,9 @@ jobs: name: Build esmini FMU uses: ./.github/workflows/build_esmini.yml - build_osi_field_checker_fmu: - name: Build OSI Field Checker FMU - uses: ./.github/workflows/build_osi_field_checker.yml + build_osi-validation: + name: Build osi-validation + uses: ./.github/workflows/build_osi-validation.yml build_openmcx: name: Build OpenMCx @@ -29,7 +29,7 @@ jobs: name: Generate Integration Test Paths steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Generate matrix with all integration tests id: set-matrix working-directory: test/integration @@ -39,7 +39,7 @@ jobs: matrix: ${{ steps.set-matrix.outputs.matrix }} run_integration_test: - needs: [build_tracefile_player, build_tracefile_writer, build_openmcx, build_osi_field_checker_fmu, build_esmini, generate_integration_test_paths] + needs: [build_tracefile_player, build_tracefile_writer, build_osi-validation, build_openmcx, build_esmini, generate_integration_test_paths] name: Integration Test runs-on: ubuntu-latest strategy: @@ -52,55 +52,55 @@ jobs: run: echo ${{ github.workspace }}/${{ matrix.path }} - name: Checkout Model - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Cache Protobuf id: cache-protobuf - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: protobuf-21.12 key: ${{ runner.os }}-protobuf - name: Cache Model FMU id: cache-model-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/model_fmu key: ${{ runner.os }}-model-fmu-${{ github.sha }} - name: Cache Tracefile Player FMU id: cache-tracefile-player-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/tracefile_player_fmu key: ${{ runner.os }}-tracefile-player-fmu - name: Cache Tracefile Writer FMU id: cache-tracefile-writer-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/tracefile_writer_fmu key: ${{ runner.os }}-tracefile-writer-fmu - name: Cache esmini FMU id: cache-esmini-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/esmini_fmu key: ${{ runner.os }}-esmini-fmu - - name: Cache OSI Field Checker - id: cache-osi-field-checker - uses: actions/cache@v3 + - name: Cache osi-validation + id: cache-osi-validation + uses: actions/cache@v4 with: - path: /tmp/osi-field-checker - key: ${{ runner.os }}-osi-field-checker + path: /tmp/osi-validation + key: ${{ runner.os }}-osi-validation - name: Cache OpenMCx id: cache-openmcx - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: openmcx key: ${{ runner.os }}-openmcx @@ -108,6 +108,35 @@ jobs: - name: Install dependencies run: sudo apt install -y libxml2-dev zlib1g-dev libzip-dev + - name: Check For Input Trace Files + id: check-for-input-trace-files + working-directory: ./test/integration/${{ matrix.path }} + run: | + ( count=`ls -1 *.osi 2>/dev/null | wc -l` + if [ $count == 0 ]; then + echo No trace file found. + echo "found_trace=0" >> $GITHUB_OUTPUT + elif [ $count == 1 ]; then + echo One trace file found. + echo "found_trace=1" >> $GITHUB_OUTPUT + filename=$(ls -1 *.osi) + else + echo More than one trace file. + echo "found_trace=1" >> $GITHUB_OUTPUT + fi + ) + + - name: Check Input Trace Files with osi-validation and model input rules + if: steps.check-for-input-trace-files.outputs.found_trace == 1 + run: | + if [ -d "./rules/input_rules" ]; then + source /tmp/osi-validation/.venv/bin/activate + for filename in ./test/integration/${{ matrix.path }}/*.osi; do + osivalidator --rules ./rules/input_rules --data ${filename} + done + else echo "No custom input rules found in ./rules/input_rules"; + fi + - name: Create Output Folder working-directory: ./test/integration/${{ matrix.path }} run: mkdir output @@ -116,8 +145,8 @@ jobs: id: cosimulation run: ./openmcx/install/openmcx ./test/integration/${{ matrix.path }}/SystemStructure.ssd - - name: Check For Trace Files - id: check-for-trace-files + - name: Check For Output Trace Files + id: check-for-output-trace-files working-directory: ./test/integration/${{ matrix.path }}/output run: | ( count=`ls -1 *.osi 2>/dev/null | wc -l` @@ -125,22 +154,45 @@ jobs: echo No trace file found. echo "found_trace=0" >> $GITHUB_OUTPUT elif [ $count == 1 ]; then + echo One trace file found. echo "found_trace=1" >> $GITHUB_OUTPUT filename=$(ls -1 *.osi) echo "trace_file_name=${filename}" >> $GITHUB_OUTPUT else echo More than one trace file. - echo "found_trace=0" >> $GITHUB_OUTPUT + echo "found_trace=1" >> $GITHUB_OUTPUT + zip ${{ matrix.path }}.zip *.osi + echo "trace_file_name=${{ matrix.path }}.zip" >> $GITHUB_OUTPUT fi ) - - name: Archive Trace File - if: steps.check-for-trace-files.outputs.found_trace == 1 - uses: actions/upload-artifact@v3 + - name: Archive Output Trace Files + if: steps.check-for-output-trace-files.outputs.found_trace == 1 + uses: actions/upload-artifact@v4 with: - name: ${{ steps.check-for-trace-files.outputs.trace_file_name }} - path: ./test/integration/${{ matrix.path }}/output/${{ steps.check-for-trace-files.outputs.trace_file_name }} - + name: ${{ steps.check-for-output-trace-files.outputs.trace_file_name }} + path: ./test/integration/${{ matrix.path }}/output/${{ steps.check-for-output-trace-files.outputs.trace_file_name }} + + - name: Check Output Trace Files with osi-validation and default rules + if: steps.check-for-output-trace-files.outputs.found_trace == 1 + working-directory: ./test/integration/${{ matrix.path }}/output + run: | + source /tmp/osi-validation/.venv/bin/activate + for filename in ./*.osi; do + osivalidator --rules /tmp/osi-validation/rules/ --data ${filename} + done + + - name: Check Output Trace Files with osi-validation and model output rules + if: steps.check-for-output-trace-files.outputs.found_trace == 1 + run: | + if [ -d "./rules/output_rules" ]; then + source /tmp/osi-validation/.venv/bin/activate + for filename in ./test/integration/${{ matrix.path }}/output/*.osi; do + osivalidator --rules ./rules/output_rules --data ${filename} + done + else echo "No custom output rules found in ./rules/output_rules"; + fi + - name: Check For Python Scripts id: check-for-python-scripts working-directory: ./test/integration/${{ matrix.path }} @@ -173,7 +225,7 @@ jobs: - name: Run Trace File Analysis if: steps.check-for-python-scripts.outputs.found_script == 1 working-directory: ./test/integration/${{ matrix.path }} - run: python3 ${{ steps.check-for-python-scripts.outputs.python_file_name }} output/${{ steps.check-for-trace-files.outputs.trace_file_name }} + run: python3 ${{ steps.check-for-python-scripts.outputs.python_file_name }} output/${{ steps.check-for-output-trace-files.outputs.trace_file_name }} - name: Failed? if: steps.cosimulation.outputs.failed == 1 diff --git a/.github/workflows/cl3.yml b/.github/workflows/cl3.yml new file mode 100644 index 0000000..8721357 --- /dev/null +++ b/.github/workflows/cl3.yml @@ -0,0 +1,211 @@ +name: Credibility Assessment Level 3 + +on: + workflow_call: + +jobs: + generate_behavior_test_paths: + runs-on: ubuntu-latest + name: Generate Behavior Test Paths + + steps: + - uses: actions/checkout@v4 + - name: Generate matrix with all behavior tests + id: set-matrix + working-directory: test/behavior + run: | + echo "matrix=$(ls -l | grep '^d' | awk -F ' ' '{print $9}' | grep -Po '\d{3}.*' | jq -R -s -c 'split("\n") | map(select(length > 0))')" >> $GITHUB_OUTPUT + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + + run_behavior_test: + needs: [generate_behavior_test_paths] + name: Behavior Test + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + path: ${{ fromJson(needs.generate_behavior_test_paths.outputs.matrix) }} + + steps: + - name: Print matrix path + run: echo ${{ github.workspace }}/${{ matrix.path }} + + - name: Checkout Model + uses: actions/checkout@v4 + with: + submodules: true + + - name: Cache Protobuf + id: cache-protobuf + uses: actions/cache@v4 + with: + path: protobuf-21.12 + key: ${{ runner.os }}-protobuf + + - name: Cache Model FMU + id: cache-model-fmu + uses: actions/cache@v4 + with: + path: /tmp/model_fmu + key: ${{ runner.os }}-model-fmu-${{ github.sha }} + + - name: Cache Tracefile Player FMU + id: cache-tracefile-player-fmu + uses: actions/cache@v4 + with: + path: /tmp/tracefile_player_fmu + key: ${{ runner.os }}-tracefile-player-fmu + + - name: Cache Tracefile Writer FMU + id: cache-tracefile-writer-fmu + uses: actions/cache@v4 + with: + path: /tmp/tracefile_writer_fmu + key: ${{ runner.os }}-tracefile-writer-fmu + + - name: Cache esmini FMU + id: cache-esmini-fmu + uses: actions/cache@v4 + with: + path: /tmp/esmini_fmu + key: ${{ runner.os }}-esmini-fmu + + - name: Cache osi-validation + id: cache-osi-validation + uses: actions/cache@v4 + with: + path: /tmp/osi-validation + key: ${{ runner.os }}-osi-validation + + - name: Cache OpenMCx + id: cache-openmcx + uses: actions/cache@v4 + with: + path: openmcx + key: ${{ runner.os }}-openmcx + + - name: Install dependencies + run: sudo apt install -y libxml2-dev zlib1g-dev libzip-dev + + - name: Install ProtoBuf + working-directory: protobuf-21.12 + run: sudo make install && sudo ldconfig + + - name: Check if analysis script exists + id: check_analysis_script + uses: andstor/file-existence-action@v3 + with: + files: test/behavior/${{ matrix.path }}/analyze.py + + - name: Check if trace file generator exists + id: check_trace_generator + uses: andstor/file-existence-action@v3 + with: + files: test/behavior/${{ matrix.path }}/generate_test_trace.py + + - name: Install OSI for python + if: steps.check_analysis_script.outputs.files_exists == 'true' || steps.check_trace_generator.outputs.files_exists == 'true' + working-directory: ./lib/open-simulation-interface + run: | + python3 -m pip install protobuf==4.21.12 + python3 -m pip install . + + - name: Run test trace generation + if: steps.check_trace_generator.outputs.files_exists == 'true' + working-directory: ./test/behavior/${{ matrix.path }} + run: python3 generate_test_trace.py + + - name: Check For Input Trace Files + id: check-for-input-trace-files + working-directory: ./test/behavior/${{ matrix.path }} + run: | + ( count=`ls -1 *.osi 2>/dev/null | wc -l` + if [ $count == 0 ]; then + echo No trace file found. + echo "found_trace=0" >> $GITHUB_OUTPUT + elif [ $count == 1 ]; then + echo One trace file found. + echo "found_trace=1" >> $GITHUB_OUTPUT + filename=$(ls -1 *.osi) + else + echo More than one trace file. + echo "found_trace=1" >> $GITHUB_OUTPUT + fi + ) + + - name: Check Input Trace Files with osi-validation and model input rules + if: steps.check-for-input-trace-files.outputs.found_trace == 1 + run: | + if [ -d "./rules/input_rules" ]; then + source /tmp/osi-validation/.venv/bin/activate + for filename in ./test/behavior/${{ matrix.path }}/*.osi; do + osivalidator --rules ./rules/input_rules --data ${filename} + done + else echo "No custom input rules found in ./rules/input_rules"; + fi + + - name: Create Output Folder + working-directory: ./test/behavior/${{ matrix.path }} + run: mkdir output + + - name: Run OpenMCx + id: cosimulation + run: ./openmcx/install/openmcx ./test/behavior/${{ matrix.path }}/SystemStructure.ssd + + - name: Check For Output Trace Files + id: check-for-output-trace-files + working-directory: ./test/behavior/${{ matrix.path }}/output + run: | + ( count=`ls -1 *.osi 2>/dev/null | wc -l` + if [ $count == 0 ]; then + echo No trace file found. + echo "found_trace=0" >> $GITHUB_OUTPUT + elif [ $count == 1 ]; then + echo One trace file found. + echo "found_trace=1" >> $GITHUB_OUTPUT + filename=$(ls -1 *.osi) + echo "trace_file_name=${filename}" >> $GITHUB_OUTPUT + else + echo More than one trace file. + echo "found_trace=1" >> $GITHUB_OUTPUT + zip ${{ matrix.path }}.zip *.osi + echo "trace_file_name=${{ matrix.path }}.zip" >> $GITHUB_OUTPUT + fi + ) + + - name: Archive Trace File + if: steps.check-for-output-trace-files.outputs.found_trace == 1 + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.check-for-output-trace-files.outputs.trace_file_name }} + path: ./test/behavior/${{ matrix.path }}/output/${{ steps.check-for-output-trace-files.outputs.trace_file_name }} + + - name: Check Output Trace Files with osi-validation and default rules + if: steps.check-for-output-trace-files.outputs.found_trace == 1 + working-directory: ./test/behavior/${{ matrix.path }}/output + run: | + source /tmp/osi-validation/.venv/bin/activate + for filename in ./*.osi; do + osivalidator --rules /tmp/osi-validation/rules/ --data ${filename} + done + + - name: Check Output Trace Files with osi-validation and model output rules + if: steps.check-for-output-trace-files.outputs.found_trace == 1 + run: | + if [ -d "./rules/output_rules" ]; then + source /tmp/osi-validation/.venv/bin/activate + for filename in ./test/behavior/${{ matrix.path }}/output/*.osi; do + osivalidator --rules ./rules/output_rules --data ${filename} + done + else echo "No custom output rules found in ./rules/output_rules"; + fi + + - name: Run Trace File Analysis + if: steps.check_analysis_script.outputs.files_exists == 'true' + working-directory: ./test/behavior/${{ matrix.path }} + run: python3 analyze.py output/${{ steps.check-for-output-trace-files.outputs.trace_file_name }} + + - name: Failed? + if: steps.cosimulation.outputs.failed == 1 + run: exit 1 diff --git a/.github/workflows/cpp-linter.yml b/.github/workflows/cpp-linter.yml index acbb48f..41e8f3c 100644 --- a/.github/workflows/cpp-linter.yml +++ b/.github/workflows/cpp-linter.yml @@ -9,13 +9,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Model - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Cache Protobuf id: cache-protobuf - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: protobuf-21.12 key: ${{ runner.os }}-protobuf diff --git a/.github/workflows/credibility_assessment.yml b/.github/workflows/credibility_assessment.yml index 8d9a646..28aff45 100644 --- a/.github/workflows/credibility_assessment.yml +++ b/.github/workflows/credibility_assessment.yml @@ -19,3 +19,8 @@ jobs: name: CL 2 needs: cl1 uses: ./.github/workflows/cl2.yml + + cl3: + name: CL 3 + needs: cl2 + uses: ./.github/workflows/cl3.yml diff --git a/.github/workflows/fmu_artifact.yml b/.github/workflows/fmu_artifact.yml index 503e2e4..ee92410 100644 --- a/.github/workflows/fmu_artifact.yml +++ b/.github/workflows/fmu_artifact.yml @@ -11,13 +11,13 @@ jobs: steps: - name: Cache Model FMU id: cache-model-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/model_fmu key: ${{ runner.os }}-model-fmu-${{ github.sha }} - name: Archive built FMU - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ github.event.repository.name }} path: /tmp/model_fmu/${{ github.event.repository.name }}.fmu diff --git a/.github/workflows/fmu_checker.yml b/.github/workflows/fmu_checker.yml index d923d0a..9204bdc 100644 --- a/.github/workflows/fmu_checker.yml +++ b/.github/workflows/fmu_checker.yml @@ -11,14 +11,34 @@ jobs: steps: - name: Cache Model FMU id: cache-model-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/model_fmu key: ${{ runner.os }}-model-fmu-${{ github.sha }} + - name: Cache Protobuf + id: cache-protobuf + uses: actions/cache@v4 + with: + path: protobuf-21.12 + key: ${{ runner.os }}-protobuf + + - name: Download ProtoBuf + if: steps.cache-protobuf.outputs.cache-hit != 'true' + run: curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protobuf-all-21.12.tar.gz && tar xzvf protobuf-all-21.12.tar.gz + + - name: Build ProtoBuf + if: steps.cache-protobuf.outputs.cache-hit != 'true' + working-directory: protobuf-21.12 + run: ./configure DIST_LANG=cpp --disable-shared CXXFLAGS="-fPIC" && make -j4 + + - name: Install ProtoBuf + working-directory: protobuf-21.12 + run: sudo make install && sudo ldconfig + - name: Cache FMUComplianceChecker id: cache-fmu-checker - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/FMUComplianceChecker key: ${{ runner.os }}-fmu-checker @@ -54,13 +74,13 @@ jobs: steps: - name: Cache Model FMU id: cache-model-fmu - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /tmp/model_fmu key: ${{ runner.os }}-model-fmu-${{ github.sha }} - name: Install FMPy - run: python -m pip install fmpy[complete] + run: python -m pip install fmpy==0.3.16 - name: Run FMPy Validate working-directory: /tmp/model_fmu diff --git a/.github/workflows/markdown.yml b/.github/workflows/markdown.yml index 6c3dd4d..72df403 100644 --- a/.github/workflows/markdown.yml +++ b/.github/workflows/markdown.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: markdown-lint uses: articulate/actions-markdownlint@v1 with: diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 4d1d1f8..e8c60f9 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -9,19 +9,19 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Model - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Check unit tests exist id: check_files - uses: andstor/file-existence-action@v2 + uses: andstor/file-existence-action@v3 with: files: "test/unit" - name: Cache Protobuf id: cache-protobuf - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: protobuf-21.12 key: ${{ runner.os }}-protobuf From 464c74d51858225efe643539950a9f98b09b6781 Mon Sep 17 00:00:00 2001 From: ClemensLinnhoff Date: Wed, 26 Jun 2024 14:13:32 +0200 Subject: [PATCH 2/4] Swap out integration tests Signed-off-by: ClemensLinnhoff --- ...40617T163554Z_sv_370_244_20_one_object.osi | Bin 0 -> 7476 bytes .../001_smoke_test_tracefile/README.md | 28 ++ .../SystemStructure.ssd | 109 +++++ .../system_structure.png | Bin 0 -> 43761 bytes .../Catalogs/Vehicles/VehicleCatalog.xosc | 435 ++++++++++++++++++ .../002_smoke_test_scenario/README.md | 24 + .../SystemStructure.ssd | 112 +++++ .../cut-in_simple.xosc | 188 ++++++++ .../straight_500m.xodr | 116 +++++ .../system_structure.png | Bin 0 -> 39434 bytes ...40617T163554Z_sv_370_244_20_one_object.osi | Bin 0 -> 7476 bytes .../003_output_osi_fields/README.md | 28 ++ .../003_output_osi_fields/SystemStructure.ssd | 151 ++++++ .../system_structure.png | Bin 0 -> 51264 bytes 14 files changed, 1191 insertions(+) create mode 100644 test/integration/001_smoke_test_tracefile/20240617T163554Z_sv_370_244_20_one_object.osi create mode 100644 test/integration/001_smoke_test_tracefile/README.md create mode 100644 test/integration/001_smoke_test_tracefile/SystemStructure.ssd create mode 100644 test/integration/001_smoke_test_tracefile/system_structure.png create mode 100644 test/integration/002_smoke_test_scenario/Catalogs/Vehicles/VehicleCatalog.xosc create mode 100644 test/integration/002_smoke_test_scenario/README.md create mode 100644 test/integration/002_smoke_test_scenario/SystemStructure.ssd create mode 100644 test/integration/002_smoke_test_scenario/cut-in_simple.xosc create mode 100644 test/integration/002_smoke_test_scenario/straight_500m.xodr create mode 100644 test/integration/002_smoke_test_scenario/system_structure.png create mode 100644 test/integration/003_output_osi_fields/20240617T163554Z_sv_370_244_20_one_object.osi create mode 100644 test/integration/003_output_osi_fields/README.md create mode 100644 test/integration/003_output_osi_fields/SystemStructure.ssd create mode 100644 test/integration/003_output_osi_fields/system_structure.png diff --git a/test/integration/001_smoke_test_tracefile/20240617T163554Z_sv_370_244_20_one_object.osi b/test/integration/001_smoke_test_tracefile/20240617T163554Z_sv_370_244_20_one_object.osi new file mode 100644 index 0000000000000000000000000000000000000000..fae9beeedeb7e44b7e187575642a84df0831a5df GIT binary patch literal 7476 zcmeI$F-yZh7zW_GOR$$rF*wAQF2N~_AUNpK;^rT4RB&|)x(W^=4pxQk{sVCk6{J{j za46^?f}4}GgOdn?S9+I(Snzy<+t(>@eZ%qaaon4fGv-f7C#Xd%tVtH^+&<6Ng=BHl zZ+J}qCe6dNd04y@<6>#j;l7Y*xSpk_+9uuB>5o=uUOkg7vh3A$v&fi9=8LhHZ7LE; zGj4djt#0J5y!Z3}Znx%Fua}?tb3(ewA@?2m$!#~Z@ZTF+Qab4m^xd;H1bq}E^xvjn zh`w1wm%~ZF+dJYm>R0)w7jwjpvG2d!K=^st;tgWgIbz4y4>~6TIb?K>*fI8p z*L#Rv=ZGC+Kkj`&>^ev682e-Q)Ikmzog;P|_Ko5N(v>`5Hst5|<4SjcgPLicBX*1(YNm>vnklPt$Ux0h vu~Rdx#11u6#ZJw%5 + +## Scenario + +The scenario contained in the given trace file consists of a vehicle placed on the x-axis (y = 0) in front of the ego vehicle in the sensor's field of view. +The x-coordinates of the objects in this scenario are: + +- ego: 10 m +- ego bbcenter2rear: -1.146 m +- object: 25 m + +## Metric + +No runtime error. + +## Pass/Fail Criterion + +The test fails, if a runtime error occurs. diff --git a/test/integration/001_smoke_test_tracefile/SystemStructure.ssd b/test/integration/001_smoke_test_tracefile/SystemStructure.ssd new file mode 100644 index 0000000..662e28a --- /dev/null +++ b/test/integration/001_smoke_test_tracefile/SystemStructure.ssd @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/integration/001_smoke_test_tracefile/system_structure.png b/test/integration/001_smoke_test_tracefile/system_structure.png new file mode 100644 index 0000000000000000000000000000000000000000..b1e7e09017c20354a51d9e282e0b4e44264b3f3c GIT binary patch literal 43761 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 TU{S$1*roJV{Z096v(Wzn;_Q-k literal 0 HcmV?d00001 diff --git a/test/integration/002_smoke_test_scenario/Catalogs/Vehicles/VehicleCatalog.xosc b/test/integration/002_smoke_test_scenario/Catalogs/Vehicles/VehicleCatalog.xosc new file mode 100644 index 0000000..b96a039 --- /dev/null +++ b/test/integration/002_smoke_test_scenario/Catalogs/Vehicles/VehicleCatalog.xosc @@ -0,0 +1,435 @@ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/integration/002_smoke_test_scenario/README.md b/test/integration/002_smoke_test_scenario/README.md new file mode 100644 index 0000000..9068638 --- /dev/null +++ b/test/integration/002_smoke_test_scenario/README.md @@ -0,0 +1,24 @@ +# 002 Smoke Test Trace Scenario + +This test checks if the model runs without any runtime errors when connected to a scenario player FMU. + +## System Structure Definition + +The system consists of the [esmini scenario player FMU](https://github.com/esmini/esmini/tree/master/OSMP_FMU) and the model itself. +esmini will play the given OpenSCenario file as an input for the sensor model. +The output of the sensor model is disregarded. + +System Structure + +## Scenario + +The scenario contained in the given OpenScenario file consists of the ego vehicle driving on a straight road. +Another vehicle is overtaking from behind and cutting in front of the ego into the ego lane. + +## Metric + +No runtime error. + +## Pass/Fail Criterion + +The test fails, if a runtime error occurs. diff --git a/test/integration/002_smoke_test_scenario/SystemStructure.ssd b/test/integration/002_smoke_test_scenario/SystemStructure.ssd new file mode 100644 index 0000000..15b7873 --- /dev/null +++ b/test/integration/002_smoke_test_scenario/SystemStructure.ssd @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/integration/002_smoke_test_scenario/cut-in_simple.xosc b/test/integration/002_smoke_test_scenario/cut-in_simple.xosc new file mode 100644 index 0000000..1bc1217 --- /dev/null +++ b/test/integration/002_smoke_test_scenario/cut-in_simple.xosc @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/integration/002_smoke_test_scenario/straight_500m.xodr b/test/integration/002_smoke_test_scenario/straight_500m.xodr new file mode 100644 index 0000000..ce7c576 --- /dev/null +++ b/test/integration/002_smoke_test_scenario/straight_500m.xodr @@ -0,0 +1,116 @@ + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + +