Skip to content

docs: add IEC 62304 SOUP register #633

docs: add IEC 62304 SOUP register

docs: add IEC 62304 SOUP register #633

name: Integration Tests
on:
push:
branches: [ main, feat/phase5-integration-testing ]
pull_request:
branches: [ main ]
workflow_dispatch:
jobs:
integration-tests-ubuntu:
name: Integration Tests (Ubuntu)
runs-on: ubuntu-latest
strategy:
matrix:
build-type: [Debug, Release]
# Note: Clang removed due to transient apt package conflicts on GitHub runners
# Main CI (ci.yml) still tests Clang with proper libc++ support
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install system dependencies
run: |
# Retry logic for apt-get to handle transient failures
for i in 1 2 3; do
echo "Attempt $i: Updating package list..."
sudo apt-get update && break || {
echo "apt-get update failed, retrying in 10 seconds..."
sleep 10
}
done
# Install dependencies with retry
# Note: GCC 13+ on ubuntu-latest (24.04) has full std::format support
for i in 1 2 3; do
echo "Attempt $i: Installing dependencies..."
sudo apt-get install -y \
cmake \
ninja-build \
gcc \
g++ && break || {
echo "apt-get install failed, retrying in 10 seconds..."
sleep 10
}
done
# Verify installation
gcc --version
g++ --version
cmake --version
ninja --version
# GTest is now fetched via CMake FetchContent - no system package needed
- name: Checkout common_system (optional dependency)
continue-on-error: true
run: |
cd ..
if [ ! -d "common_system" ]; then
git clone https://github.com/kcenon/common_system.git || echo "common_system not available"
fi
- name: Cache FetchContent dependencies
uses: actions/cache@v4
with:
path: |
build/_deps
key: ${{ runner.os }}-gcc-${{ matrix.build-type }}-fetchcontent-gtest-v1.14.0
restore-keys: |
${{ runner.os }}-gcc-${{ matrix.build-type }}-fetchcontent-gtest-v1.14.0
${{ runner.os }}-gcc-fetchcontent-gtest-v1.14.0
- name: Configure CMake
env:
CC: gcc
CXX: g++
run: |
BUILD_WITH_COMMON="OFF"
if [ -d "../common_system" ]; then
BUILD_WITH_COMMON="ON"
fi
echo "=== Build Configuration ==="
echo "Compiler: GCC"
echo "Build Type: ${{ matrix.build-type }}"
echo "Common System: $BUILD_WITH_COMMON"
echo "GTest: Will be fetched via FetchContent if needed"
echo "==========================="
cmake -B build \
-G Ninja \
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
-DBUILD_INTEGRATION_TESTS=ON \
-DBUILD_WITH_COMMON_SYSTEM=$BUILD_WITH_COMMON \
-DCMAKE_PREFIX_PATH="/usr" \
--debug-find || {
echo "::error::CMake configuration failed"
echo "CMake logs:"
cat build/CMakeFiles/CMakeError.log 2>/dev/null || echo "No CMakeError.log found"
exit 1
}
- name: Build
run: |
echo "=== Building with GCC ==="
cmake --build build --config ${{ matrix.build-type }} --verbose || {
echo "::error::Build failed"
exit 1
}
- name: Run Smoke and Integration Tests
working-directory: build
timeout-minutes: 10
run: |
echo "=== Running Fast Tests (Smoke + Integration) ==="
# Debug builds run 2-3x slower due to no optimization, use longer timeout
if [ "${{ matrix.build-type }}" = "Debug" ]; then
ctest --output-on-failure --timeout 300 -L "smoke|integration" -C ${{ matrix.build-type }}
else
ctest --output-on-failure --timeout 120 -L "smoke|integration" -C ${{ matrix.build-type }}
fi
- name: Upload test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: integration-test-results-ubuntu-gcc-${{ matrix.build-type }}
path: build/Testing/Temporary/LastTest.log
integration-tests-macos:
name: Integration Tests (macOS)
runs-on: macos-latest
strategy:
matrix:
build-type: [Debug, Release]
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install system dependencies
run: |
# Note: macOS has built-in std::format support via Apple Clang
brew install cmake ninja
# GTest is now fetched via CMake FetchContent - no system package needed
- name: Checkout common_system (optional dependency)
continue-on-error: true
run: |
cd ..
if [ ! -d "common_system" ]; then
git clone https://github.com/kcenon/common_system.git || echo "common_system not available"
fi
- name: Cache FetchContent dependencies
uses: actions/cache@v4
with:
path: |
build/_deps
key: ${{ runner.os }}-${{ matrix.build-type }}-fetchcontent-gtest-v1.14.0
restore-keys: |
${{ runner.os }}-${{ matrix.build-type }}-fetchcontent-gtest-v1.14.0
${{ runner.os }}-fetchcontent-gtest-v1.14.0
- name: Configure CMake
run: |
BUILD_WITH_COMMON="OFF"
if [ -d "../common_system" ]; then
BUILD_WITH_COMMON="ON"
fi
echo "=== Build Configuration ==="
echo "Build Type: ${{ matrix.build-type }}"
echo "Common System: $BUILD_WITH_COMMON"
echo "GTest: Will be fetched via FetchContent if needed"
echo "==========================="
cmake -B build \
-G Ninja \
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
-DBUILD_INTEGRATION_TESTS=ON \
-DBUILD_WITH_COMMON_SYSTEM=$BUILD_WITH_COMMON \
--debug-find || {
echo "::error::CMake configuration failed"
echo "CMake logs:"
cat build/CMakeFiles/CMakeError.log 2>/dev/null || echo "No CMakeError.log found"
exit 1
}
- name: Build
run: cmake --build build --config ${{ matrix.build-type }}
- name: Run Smoke and Integration Tests
working-directory: build
timeout-minutes: 10
run: |
echo "=== Running Fast Tests (Smoke + Integration) ==="
# Debug builds run 2-3x slower due to no optimization, use longer timeout
if [ "${{ matrix.build-type }}" = "Debug" ]; then
ctest --output-on-failure --timeout 300 -L "smoke|integration" -C ${{ matrix.build-type }}
else
ctest --output-on-failure --timeout 120 -L "smoke|integration" -C ${{ matrix.build-type }}
fi
- name: Upload test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: integration-test-results-macos-${{ matrix.build-type }}
path: build/Testing/Temporary/LastTest.log
integration-tests-windows:
name: Integration Tests (Windows)
runs-on: windows-2022
strategy:
matrix:
build-type: [Debug, Release]
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup MSVC Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1
- name: Install system dependencies
shell: pwsh
run: |
choco install ninja -y
# GTest is now fetched via CMake FetchContent - no system package needed
# Note: MSVC 19.29+ has full std::format support (version-based detection)
- name: Checkout common_system (optional dependency)
continue-on-error: true
shell: pwsh
run: |
cd ..
if (-not (Test-Path "common_system")) {
git clone https://github.com/kcenon/common_system.git
if ($LASTEXITCODE -ne 0) { Write-Host "common_system not available" }
}
- name: Cache FetchContent dependencies
uses: actions/cache@v4
with:
path: |
build/_deps
key: ${{ runner.os }}-msvc-${{ matrix.build-type }}-fetchcontent-gtest-v1.14.0
restore-keys: |
${{ runner.os }}-msvc-${{ matrix.build-type }}-fetchcontent-gtest-v1.14.0
${{ runner.os }}-msvc-fetchcontent-gtest-v1.14.0
- name: Configure CMake
shell: pwsh
run: |
# Check if common_system is available
if (Test-Path "../common_system") {
Write-Host "Building with common_system support"
$BUILD_WITH_COMMON = "ON"
} else {
Write-Host "Building without common_system support"
$BUILD_WITH_COMMON = "OFF"
}
Write-Host "=== Build Configuration ==="
Write-Host "Compiler: MSVC"
Write-Host "Build Type: ${{ matrix.build-type }}"
Write-Host "Common System: $BUILD_WITH_COMMON"
Write-Host "GTest: Will be fetched via FetchContent if needed"
Write-Host "==========================="
# Use Ninja with MSVC - feature detection uses version-based check
cmake -B build -G Ninja `
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} `
-DCMAKE_CXX_STANDARD=20 `
-DCMAKE_CXX_FLAGS="/std:c++20 /EHsc /Zc:__cplusplus /permissive-" `
-DBUILD_INTEGRATION_TESTS=ON `
-DBUILD_WITH_COMMON_SYSTEM=$BUILD_WITH_COMMON
if ($LASTEXITCODE -ne 0) {
Write-Host "::error::CMake configuration failed"
if (Test-Path "build/CMakeFiles/CMakeError.log") {
Get-Content "build/CMakeFiles/CMakeError.log"
}
exit 1
}
- name: Build
shell: pwsh
run: |
Write-Host "=== Building with MSVC ==="
cmake --build build --config ${{ matrix.build-type }} --verbose
if ($LASTEXITCODE -ne 0) {
Write-Host "::error::Build failed"
exit 1
}
- name: Run Smoke and Integration Tests
working-directory: build
timeout-minutes: 10
shell: pwsh
run: |
Write-Host "=== Running Fast Tests (Smoke + Integration) ==="
# Debug builds run 2-3x slower due to no optimization, use longer timeout
if ("${{ matrix.build-type }}" -eq "Debug") {
ctest --output-on-failure --timeout 300 -L "smoke|integration" -C ${{ matrix.build-type }}
} else {
ctest --output-on-failure --timeout 120 -L "smoke|integration" -C ${{ matrix.build-type }}
}
- name: Upload test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: integration-test-results-windows-${{ matrix.build-type }}
path: build/Testing/Temporary/LastTest.log
coverage:
name: Integration Test Coverage
runs-on: ubuntu-latest
continue-on-error: true # Coverage is optional - don't fail workflow if it fails
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install system dependencies
run: |
# Retry logic for apt-get to handle transient failures
for i in 1 2 3; do
echo "Attempt $i: Updating package list..."
sudo apt-get update && break || {
echo "apt-get update failed, retrying in 10 seconds..."
sleep 10
}
done
# Install dependencies with retry
for i in 1 2 3; do
echo "Attempt $i: Installing dependencies..."
# GCC 13+ on ubuntu-latest has full std::format support
sudo apt-get install -y \
cmake \
ninja-build \
gcc \
g++ \
lcov && break || {
echo "apt-get install failed, retrying in 10 seconds..."
sleep 10
}
done
# Verify installation
gcc --version
g++ --version
cmake --version
ninja --version
lcov --version
# GTest is now fetched via CMake FetchContent - no system package needed
- name: Checkout common_system (optional dependency)
continue-on-error: true
run: |
cd ..
if [ ! -d "common_system" ]; then
git clone https://github.com/kcenon/common_system.git || echo "common_system not available"
fi
- name: Cache FetchContent dependencies
uses: actions/cache@v4
with:
path: |
build/_deps
key: ${{ runner.os }}-gcc-Debug-fetchcontent-gtest-v1.14.0-${{ hashFiles('cmake/ThreadSystemDependencies.cmake', 'integration_tests/CMakeLists.txt') }}
restore-keys: |
${{ runner.os }}-gcc-Debug-fetchcontent-gtest-v1.14.0-
${{ runner.os }}-fetchcontent-gtest-v1.14.0-
- name: Configure CMake with Coverage
env:
CC: gcc
CXX: g++
run: |
# Force clean build to ensure coverage flags are applied
# CMake cache can prevent new compiler flags from being picked up
rm -rf build
BUILD_WITH_COMMON="OFF"
if [ -d "../common_system" ]; then
BUILD_WITH_COMMON="ON"
fi
cmake -B build \
-G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DBUILD_INTEGRATION_TESTS=ON \
-DBUILD_WITH_COMMON_SYSTEM=$BUILD_WITH_COMMON \
-DENABLE_COVERAGE=ON \
-DCMAKE_PREFIX_PATH="/usr"
- name: Build
run: |
echo "=== Building with coverage instrumentation ==="
echo "First 50 lines of verbose build to verify flags:"
cmake --build build --verbose 2>&1 | head -50
echo "..."
echo "=== Running full build ==="
cmake --build build
- name: Generate Coverage Report
timeout-minutes: 15 # Coverage tests run 5-10x slower due to instrumentation
run: |
cd build
# Create coverage directory
mkdir -p coverage/html
# Reset coverage counters
lcov --directory . --zerocounters
# Run tests with extended timeout
# Coverage instrumentation makes tests 5-10x slower, so use 600s timeout
echo "=== Running tests for coverage (smoke + integration) ==="
ctest --output-on-failure --timeout 600 -L "smoke|integration" || {
echo "::warning::Tests failed or timed out during coverage run"
exit 1
}
# Capture coverage data
# --ignore-errors: Handle common lcov issues gracefully
# - inconsistent: Function line detection issues (inline/template functions)
# - negative: Should not occur with -fprofile-update=atomic, but handle anyway
# - mismatch: gcov/gcc version compatibility
echo "=== Capturing coverage data ==="
lcov --directory . \
--capture \
--ignore-errors inconsistent,negative,mismatch \
--output-file coverage/all.info || {
echo "::error::Failed to capture coverage data"
echo "Attempting capture with all errors ignored..."
lcov --directory . \
--capture \
--ignore-errors all \
--output-file coverage/all.info || exit 1
}
# Filter coverage data
echo "=== Filtering coverage data ==="
lcov --remove coverage/all.info \
'/usr/*' \
'*/vcpkg/*' \
'*/build/*' \
'*/unittest/*' \
'*/benchmarks/*' \
'*/samples/*' \
'*/test/*' \
--ignore-errors inconsistent,unused \
--output-file coverage/all.cleaned.info || {
echo "::error::Failed to filter coverage data"
exit 1
}
# Generate HTML report
echo "=== Generating HTML coverage report ==="
genhtml \
--demangle-cpp \
--num-spaces 2 \
--sort \
--title "Thread System Integration Coverage" \
--function-coverage \
--branch-coverage \
--ignore-errors inconsistent,unused \
--output-directory coverage/html \
coverage/all.cleaned.info || {
echo "::error::Failed to generate HTML coverage report"
exit 1
}
echo "=== Coverage report generated successfully ==="
echo "Summary:"
lcov --summary coverage/all.cleaned.info || true
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: build/coverage/all.cleaned.info
flags: integration-tests
name: integration-tests-coverage
performance-tests:
name: Performance Benchmarks
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install system dependencies
run: |
# Retry logic for apt-get to handle transient failures
for i in 1 2 3; do
echo "Attempt $i: Updating package list..."
sudo apt-get update && break || {
echo "apt-get update failed, retrying in 10 seconds..."
sleep 10
}
done
# Install dependencies with retry
for i in 1 2 3; do
echo "Attempt $i: Installing dependencies..."
# GCC 13+ on ubuntu-latest has full std::format support
sudo apt-get install -y \
cmake \
ninja-build \
gcc \
g++ && break || {
echo "apt-get install failed, retrying in 10 seconds..."
sleep 10
}
done
# Verify installation
gcc --version
g++ --version
cmake --version
ninja --version
# GTest is now fetched via CMake FetchContent - no system package needed
- name: Checkout common_system (optional dependency)
continue-on-error: true
run: |
cd ..
if [ ! -d "common_system" ]; then
git clone https://github.com/kcenon/common_system.git || echo "common_system not available"
fi
- name: Cache FetchContent dependencies
uses: actions/cache@v4
with:
path: |
build/_deps
key: ${{ runner.os }}-gcc-Release-fetchcontent-gtest-v1.14.0-${{ hashFiles('cmake/ThreadSystemDependencies.cmake', 'integration_tests/CMakeLists.txt') }}
restore-keys: |
${{ runner.os }}-gcc-Release-fetchcontent-gtest-v1.14.0-
${{ runner.os }}-fetchcontent-gtest-v1.14.0-
- name: Configure CMake
env:
CC: gcc
CXX: g++
CI: true
run: |
BUILD_WITH_COMMON="OFF"
if [ -d "../common_system" ]; then
BUILD_WITH_COMMON="ON"
fi
cmake -B build \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_INTEGRATION_TESTS=ON \
-DBUILD_PERFORMANCE_TESTS=ON \
-DBUILD_WITH_COMMON_SYSTEM=$BUILD_WITH_COMMON \
-DCMAKE_PREFIX_PATH="/usr"
- name: Build
run: cmake --build build
- name: Run Performance Benchmarks
working-directory: build
timeout-minutes: 15
env:
CI: true
run: |
echo "=== Running Performance Benchmarks ==="
ctest --output-on-failure -L "performance" -V
echo "=== Generating JSON results ==="
./bin/performance_tests --gtest_output=json:performance-results.json
- name: Upload performance results
uses: actions/upload-artifact@v4
with:
name: performance-benchmark-results
path: |
build/performance-results.json
build/Testing/Temporary/LastTest.log