Skip to content

Add comprehensive test coverage for cuddZddFuncs.c #678

Add comprehensive test coverage for cuddZddFuncs.c

Add comprehensive test coverage for cuddZddFuncs.c #678

name: Sanitizer Tests
on:
pull_request:
branches:
- main
- 4.0.0
workflow_dispatch:
concurrency:
group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
sanitizer-test:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
sanitizer: ['address', 'undefined', 'address+undefined']
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake ninja-build catch2
- name: Set sanitizer flags
id: sanitizer-flags
run: |
case "${{ matrix.sanitizer }}" in
address)
echo "flags=-fsanitize=address -fno-omit-frame-pointer" >> $GITHUB_OUTPUT
echo "name=AddressSanitizer" >> $GITHUB_OUTPUT
echo "description=Detects memory errors, buffer overflows, use-after-free" >> $GITHUB_OUTPUT
;;
undefined)
echo "flags=-fsanitize=undefined -fno-omit-frame-pointer" >> $GITHUB_OUTPUT
echo "name=UndefinedBehaviorSanitizer" >> $GITHUB_OUTPUT
echo "description=Detects undefined behavior like integer overflow, null pointer dereference" >> $GITHUB_OUTPUT
;;
address+undefined)
echo "flags=-fsanitize=address,undefined -fno-omit-frame-pointer" >> $GITHUB_OUTPUT
echo "name=AddressSanitizer+UBSan" >> $GITHUB_OUTPUT
echo "description=Combined address and undefined behavior sanitizers" >> $GITHUB_OUTPUT
;;
esac
- name: Configure with sanitizer flags
run: |
echo "πŸ”§ Configuring with ${{ steps.sanitizer-flags.outputs.name }}"
echo "πŸ“ ${{ steps.sanitizer-flags.outputs.description }}"
cmake -S . -B /tmp/build \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS="-g -O1 ${{ steps.sanitizer-flags.outputs.flags }}" \
-DCMAKE_CXX_FLAGS="-g -O1 ${{ steps.sanitizer-flags.outputs.flags }}" \
-DCMAKE_EXE_LINKER_FLAGS="${{ steps.sanitizer-flags.outputs.flags }}" \
-DCMAKE_SHARED_LINKER_FLAGS="${{ steps.sanitizer-flags.outputs.flags }}" \
-DCUDD_BUILD_TESTS=ON \
-DCUDD_BUILD_SHARED_LIBS=OFF \
-DCUDD_BUILD_WITH_STATS=ON
- name: Build
run: cmake --build /tmp/build
- name: Set sanitizer environment variables
run: |
# Common sanitizer options
echo "ASAN_OPTIONS=detect_leaks=1:abort_on_error=1:fast_unwind_on_malloc=0:symbolize=1:print_stats=1" >> $GITHUB_ENV
echo "UBSAN_OPTIONS=abort_on_error=1:print_stacktrace=1:halt_on_error=1" >> $GITHUB_ENV
echo "MSAN_OPTIONS=abort_on_error=1:print_stats=1" >> $GITHUB_ENV
# Ensure core dumps are disabled to prevent large artifacts
echo "ASAN_OPTIONS=${ASAN_OPTIONS}:abort_on_error=1:disable_coredump=1" >> $GITHUB_ENV
- name: Test with sanitizers
run: |
cd /tmp/build
echo "πŸ§ͺ Running tests with ${{ steps.sanitizer-flags.outputs.name }}"
# Set up error handling for sanitizer failures
export ASAN_SYMBOLIZER_PATH=$(which llvm-symbolizer || which addr2line)
# Run tests with detailed output
ctest --test-dir . --output-on-failure --verbose
echo "βœ… All tests passed with ${{ steps.sanitizer-flags.outputs.name }}"
- name: Test individual executables
run: |
cd /tmp/build
echo "πŸ” Testing individual executables for sanitizer issues"
# Find and test individual test executables
find . -name "*test*" -type f -executable | while read -r test_exe; do
if [ -f "$test_exe" ]; then
echo "Testing executable: $test_exe"
timeout 120 "$test_exe" || echo "⚠️ $test_exe failed or timed out"
fi
done
- name: Collect sanitizer logs
if: failure()
run: |
echo "πŸ“‹ Collecting sanitizer output and logs"
# Look for sanitizer output files
find /tmp/build -name "*.san" -o -name "*sanitizer*" -o -name "core.*" 2>/dev/null || true
# Print environment variables for debugging
echo "Environment variables:"
env | grep -E "(ASAN|UBSAN|MSAN)_OPTIONS" || true
- name: Upload sanitizer artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: sanitizer-artifacts-${{ matrix.sanitizer }}-${{ matrix.build_shared_libs }}
path: |
/tmp/build/**/*.san
/tmp/build/**/sanitizer*
/tmp/build/Testing/Temporary/LastTest.log
/tmp/build/Testing/Temporary/LastTestsFailed.log
if-no-files-found: ignore
- name: Summary
if: always()
run: |
echo "## ${{ steps.sanitizer-flags.outputs.name }} Test Summary"
echo "- Sanitizer: ${{ matrix.sanitizer }}"
echo "- Description: ${{ steps.sanitizer-flags.outputs.description }}"
if [ -f "/tmp/build/Testing/Temporary/LastTestsFailed.log" ]; then
echo "❌ Some tests failed with sanitizer errors"
echo "Check the sanitizer artifacts for detailed error information"
else
echo "βœ… All tests passed - no memory errors or undefined behavior detected"
fi
# Show memory usage stats if available
if [ -n "$ASAN_OPTIONS" ] && echo "$ASAN_OPTIONS" | grep -q "print_stats=1"; then
echo "πŸ“Š Memory usage statistics should be available in the test output above"
fi