# Syntax reference https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: thread sanitizer

on:
  push:
    branches:
      - 'main'
      - 'releases/**'
    tags:
      - '2.*'
  pull_request:

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-22.04

    env:
      QT_VERSION: 5.15.2
      TSAN_OPTIONS: halt_on_error=1
      # TODO: figure out why there are cache misses with PCH enabled
      CCACHE_SLOPPINESS: pch_defines,time_macros

    steps:
      - uses: actions/checkout@v3

      - name: ccache
        uses: hendrikmuhs/ccache-action@v1.2.11
        with:
          key: ${{ github.workflow }}-${{ github.job }}-${{ matrix.os }}

      - name: Set up Python 3.12
        uses: actions/setup-python@v4
        with:
          python-version: '3.12'
          check-latest: true

      - name: Install missing software on ubuntu
        run: |
          sudo apt-get update
          sudo apt-get install -y cmake make libpcre3-dev libboost-container-dev libxml2-utils

      - name: Install clang
        run: |
          sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14
          wget https://apt.llvm.org/llvm.sh
          chmod +x llvm.sh
          sudo ./llvm.sh 18

      - name: Install Qt ${{ env.QT_VERSION }}
        if: false
        uses: jurplel/install-qt-action@v3
        with:
          version: ${{ env.QT_VERSION }}
          modules: 'qtcharts'
          cache: true

      - name: Install missing Python packages
        run: |
          python3 -m pip install pip --upgrade
          python3 -m pip install pytest
          python3 -m pip install pytest-timeout

      - name: CMake
        run: |
          cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=Off -DWITH_QCHART=Off -DUSE_MATCHCOMPILER=Verify -DANALYZE_THREAD=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=Off -DDISABLE_DMAKE=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
        env:
          CC: clang-18
          CXX: clang++-18

      - name: Build cppcheck
        run: |
          cmake --build cmake.output --target cppcheck -- -j $(nproc)

      - name: Build test
        run: |
          cmake --build cmake.output --target testrunner -- -j $(nproc)

      - name: Run tests
        run: ./cmake.output/bin/testrunner

      - name: Run cfg tests
        run: |
          cmake --build cmake.output --target checkcfg -- -j $(nproc)

      # TODO: we should use CTest instead to parallelize tests but the start-up overhead will slow things down
      - name: Run CTest
        if: false
        run: |
          ctest --test-dir cmake.output --output-on-failure -j$(nproc)

      - name: Run test/cli
        run: |
          pwd=$(pwd)
          cd test/cli
          TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv
        env:
          TEST_CPPCHECK_INJECT_EXECUTOR: thread

      - name: Run test/cli (-j2)
        run: |
          pwd=$(pwd)
          cd test/cli
          TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv
        env:
          TEST_CPPCHECK_INJECT_J: 2

      - name: Run test/cli (--clang)
        if: false
        run: |
          pwd=$(pwd)
          cd test/cli
          TEST_CPPCHECK_EXE_LOOKUP_PATH="$pwd/cmake.output" python3 -m pytest -Werror --strict-markers -vv
        env:
          TEST_CPPCHECK_INJECT_CLANG: clang

      - name: Generate dependencies
        if: false
        run: |
          # make sure auto-generated GUI files exist
          make -C cmake.output autogen
          make -C cmake.output gui-build-deps triage-build-ui-deps

      # TODO: disabled for now as it takes around 40 minutes to finish
      # set --error-exitcode=0 so we only fail on sanitizer issues - since it uses threads for execution it will exit the whole process on the first issue
      - name: Self check
        if: false
        run: |
          selfcheck_options="-q -j$(nproc) --std=c++11 --template=selfcheck --showtime=top5_summary -D__GNUC__ --error-exitcode=0 --inline-suppr --suppressions-list=.selfcheck_suppressions --library=gnu --inconclusive --enable=style,performance,portability,warning,missingInclude,internal --exception-handling --debug-warnings --check-level=exhaustive"
          selfcheck_options="$selfcheck_options --executor=thread"
          cppcheck_options="-D__CPPCHECK__ -DCHECK_INTERNAL -DHAVE_RULES --library=cppcheck-lib -Ilib -Iexternals/simplecpp/ -Iexternals/tinyxml2"
          ec=0
          ./cmake.output/bin/cppcheck $selfcheck_options externals/simplecpp || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json -DCHECK_INTERNAL cli lib || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=68 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt --addon=naming.json -Icmake.output/gui -Igui gui/*.cpp cmake.output/gui/*.cpp || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli test/*.cpp tools/*.cpp || ec=1
          ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -DQ_MOC_OUTPUT_REVISION=68 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage/*.cpp || ec=1
          exit $ec
