tests: cover every SQL column type's ddl2cpp mapping on all three DBM… #2893
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build | |
| permissions: | |
| contents: write | |
| on: | |
| merge_group: | |
| push: | |
| paths-ignore: | |
| - "mkdocs.yml" | |
| - "*.sh" | |
| branches: | |
| - master | |
| pull_request: | |
| paths-ignore: | |
| - "docs/**" | |
| - "LICENSE.txt" | |
| - "mkdocs.yml" | |
| - "*.md" | |
| branches: | |
| - master | |
| concurrency: | |
| group: build-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| CTEST_OUTPUT_ON_FAILURE: 1 | |
| SCCACHE_GHA_ENABLED: "true" | |
| CLANG_TOOLS_VERSION: "22" | |
| # stdexec is resolved via CPM on the non-vcpkg (Linux/macOS) legs; cache the clone across configures. | |
| CPM_SOURCE_CACHE: ${{ github.workspace }}/.cpm-cache | |
| jobs: | |
| # {{{ Common checks | |
| check_PR_TODOs: | |
| name: "Check PR-TODOs" | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: "Checking for open PR-related TODO items" | |
| run: ./scripts/check-pr-todos.sh | |
| check_clang_format: | |
| name: "Check C++ style" | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v2 | |
| with: | |
| #persist-credentials: true | |
| repository: ${{ github.event.pull_request.head.repo.full_name }} | |
| ref: ${{ github.event.pull_request.head.ref }} | |
| # token: ${{ secrets.CLANG_FORMAT_PAT }} | |
| - name: "Install clang-format" | |
| run: | | |
| wget https://apt.llvm.org/llvm.sh | |
| chmod +x llvm.sh | |
| sudo ./llvm.sh ${{ env.CLANG_TOOLS_VERSION }} | |
| sudo apt -qy install clang-format-${{ env.CLANG_TOOLS_VERSION }} | |
| - name: "Run clang-format" | |
| run: | | |
| git ls-files '*.h' '*.hpp' '*.cpp' \ | |
| | grep -v '^src/examples/test_chinook/entities/' \ | |
| | xargs clang-format-${{ env.CLANG_TOOLS_VERSION }} --dry-run --Werror --style=file | |
| # does not work for now | |
| # - uses: EndBug/add-and-commit@v9 | |
| # if: github.event.pull_request.head.repo.full_name == github.repository | |
| # with: | |
| # message: 'Committing clang-format changes' | |
| # default_author: github_actions | |
| check_docs: | |
| name: "Check documentation coverage" | |
| runs-on: ubuntu-24.04 | |
| if: github.ref != 'refs/heads/master' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Fetch tags | |
| run: git fetch --prune --unshallow --tags | |
| - name: "update APT database" | |
| run: sudo apt -q update | |
| - name: "install dependencies" | |
| run: sudo apt install -y cmake ninja-build doxygen g++-14 catch2 unixodbc-dev sqlite3 libsqlite3-dev uuid-dev libyaml-cpp-dev libzip-dev | |
| - name: "cmake" | |
| run: cmake --preset gcc-release -D LIGHTWEIGHT_BUILD_DOCUMENTATION=ON -D LIGHTWEIGHT_DOCS_WARN_AS_ERROR=ON | |
| - name: "check documentation" | |
| run: cmake --build --preset gcc-release --target doc | |
| - name: "check doc code snippets are in sync with tested source" | |
| run: python3 scripts/check-doc-snippets.py | |
| check_clang_tidy: | |
| name: "Check clang-tidy" | |
| runs-on: ubuntu-24.04 | |
| if: github.ref != 'refs/heads/master' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Fetch tags | |
| run: git fetch --prune --unshallow --tags | |
| - name: ccache | |
| uses: hendrikmuhs/ccache-action@v1.2 | |
| with: | |
| key: "ccache-ubuntu2404-clang-tidy" | |
| max-size: 256M | |
| - name: "update APT database" | |
| run: sudo apt -q update | |
| - name: Install clang | |
| run: | | |
| wget https://apt.llvm.org/llvm.sh | |
| chmod +x llvm.sh | |
| sudo ./llvm.sh ${{ env.CLANG_TOOLS_VERSION }} | |
| sudo apt -qy install clang-tidy-${{ env.CLANG_TOOLS_VERSION }} clang-tools-${{ env.CLANG_TOOLS_VERSION }} | |
| which clang-tidy-${{ env.CLANG_TOOLS_VERSION }} | |
| which run-clang-tidy-${{ env.CLANG_TOOLS_VERSION }} | |
| - name: "install dependencies" | |
| run: sudo apt install -y cmake ninja-build catch2 unixodbc-dev sqlite3 libsqlite3-dev libsqliteodbc uuid-dev libyaml-cpp-dev gcc-14 libzip-dev | |
| - name: "cmake" | |
| run: | | |
| cmake --preset clang-debug \ | |
| -D CMAKE_CXX_COMPILER=clang++-${{ env.CLANG_TOOLS_VERSION }} \ | |
| -D CMAKE_C_COMPILER=clang-${{ env.CLANG_TOOLS_VERSION }} \ | |
| -B build | |
| - name: "run clang-tidy" | |
| run: run-clang-tidy-${{ env.CLANG_TOOLS_VERSION }} -p ./build -clang-tidy-binary clang-tidy-${{ env.CLANG_TOOLS_VERSION }} -config-file .clang-tidy -header-filter='^(?!(.*/)?stdexec-src/|(.*/)?libzip-src/).*$' -source-filter='^(?!.*_deps/).*$' | |
| # }}} | |
| # {{{ Windows | |
| windows: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| preset: ["cl-debug", "clangcl-debug"] | |
| name: "Windows-${{ matrix.preset }}" | |
| runs-on: windows-2025 | |
| env: | |
| # Route sccache through the GitHub Actions cache backend. Without these | |
| # two the sccache binary installed below is never consulted: it needs a | |
| # storage backend, and CMake needs to be told to launch the compiler | |
| # through it (see CMAKE_*_COMPILER_LAUNCHER on the configure step). | |
| SCCACHE_GHA_ENABLED: "true" | |
| # A compiler cache must never be able to break the build. Without this, | |
| # an unreachable or erroring cache backend makes sccache fail the compile | |
| # itself: v0.17.0 aborted every invocation with "Server startup failed: | |
| # cache storage failed to read" when GitHub's artifactcache endpoint | |
| # answered HTTP 400. With it, sccache falls back to compiling directly. | |
| SCCACHE_IGNORE_SERVER_IO_ERROR: "1" | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Fetch tags | |
| run: git fetch --prune --unshallow --tags | |
| - name: Run sccache-cache | |
| # Kept current: the action resolves the sccache build, and newer | |
| # releases track changes to GitHub's cache API. | |
| uses: mozilla-actions/sccache-action@v0.0.11 | |
| - name: "vcpkg: Install dependencies" | |
| run: | | |
| git clone https://github.com/microsoft/vcpkg.git ${{ runner.workspace }}\vcpkg | |
| ${{ runner.workspace }}\vcpkg\bootstrap-vcpkg.bat | |
| - name: "Install SQLite3 for Win32" | |
| run: | | |
| choco install sqliteodbc | |
| choco install sqlite | |
| - name: "Install ninja" | |
| run: | | |
| choco install ninja | |
| - name: "Generate build files" | |
| # MSVC/clang-cl need /Z7 rather than /Zi for sccache to be able to cache | |
| # objects: /Zi writes debug info to a shared .pdb, which defeats caching. | |
| run: > | |
| cmake --preset ${{ matrix.preset }} | |
| -D CMAKE_C_COMPILER_LAUNCHER=sccache | |
| -D CMAKE_CXX_COMPILER_LAUNCHER=sccache | |
| -D CMAKE_MSVC_DEBUG_INFORMATION_FORMAT=Embedded | |
| -D CMAKE_POLICY_DEFAULT_CMP0141=NEW | |
| env: | |
| VCPKG_ROOT: "${{ runner.workspace }}/vcpkg" | |
| - name: "Build" | |
| run: cmake --build --preset ${{ matrix.preset }} | |
| - name: "sccache stats" | |
| # Surfaces the cache hit rate in the job log; a run showing 0 hits after | |
| # the first build on a branch means the wiring above regressed. | |
| run: sccache --show-stats | |
| # NB: Don't run tests here; the windows_dbms_test_matrix job below runs | |
| # the suite against each supported database in parallel. | |
| - name: "Install (stage tests for upload)" | |
| if: ${{ matrix.preset == 'cl-debug' }} | |
| shell: pwsh | |
| run: | | |
| cmake --install out/build/${{ matrix.preset }} ` | |
| --prefix out/install/${{ matrix.preset }} ` | |
| --config Debug | |
| # Belt-and-braces: copy vcpkg-deployed runtime DLLs next to the | |
| # binaries so the artifact is self-contained even if the install | |
| # rule misses any RUNTIME_DEPENDENCIES. | |
| $dllSrc = "out/build/${{ matrix.preset }}/target/Debug" | |
| if (Test-Path $dllSrc) { | |
| Copy-Item -Path "$dllSrc/*.dll" ` | |
| -Destination "out/install/${{ matrix.preset }}/bin/" ` | |
| -Force -ErrorAction SilentlyContinue | |
| } | |
| - name: "Upload unit tests" | |
| if: ${{ matrix.preset == 'cl-debug' }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: cl-debug-tests | |
| path: out/install/${{ matrix.preset }}/ | |
| retention-days: 1 | |
| windows_dbms_test_matrix: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - database: "SQLite3" | |
| test_env: "sqlite3" | |
| - database: "MS SQL Server (LocalDB)" | |
| test_env: "mssql" | |
| - database: "PostgreSQL" | |
| test_env: "postgres" | |
| name: "Windows Tests (${{ matrix.database }})" | |
| runs-on: windows-2025 | |
| needs: [windows] | |
| # Hard ceiling so a single hung dbtool invocation can't stall a runner for | |
| # 6 hours. Observed runtimes: SQLite ~50s, PostgreSQL ~12 min, MSSQL | |
| # LocalDB ~2 min — 30 min gives PostgreSQL ~3x headroom. | |
| timeout-minutes: 30 | |
| steps: | |
| - name: "Download unit test binaries" | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: cl-debug-tests | |
| path: install | |
| - name: "Install Python YAML" | |
| shell: pwsh | |
| run: python -m pip install --disable-pip-version-check pyyaml | |
| - name: "Install SQLite3 ODBC driver" | |
| if: ${{ matrix.test_env == 'sqlite3' }} | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| # The chocolatey `sqliteodbc` package was delisted from the community | |
| # feed, so install Christian Werner's NSIS installer directly. | |
| $url = "http://www.ch-werner.de/sqliteodbc/sqliteodbc_w64.exe" | |
| $installer = Join-Path $env:RUNNER_TEMP "sqliteodbc_w64.exe" | |
| Invoke-WebRequest -Uri $url -OutFile $installer | |
| Start-Process -FilePath $installer -ArgumentList "/S" -Wait -NoNewWindow | |
| - name: "Setup MS SQL Server (LocalDB)" | |
| if: ${{ matrix.test_env == 'mssql' }} | |
| shell: pwsh | |
| run: | | |
| sqllocaldb info | |
| sqllocaldb start MSSQLLocalDB | |
| sqlcmd -S "(LocalDB)\MSSQLLocalDB" -Q "CREATE DATABASE TestDB;" | |
| sqlcmd -S "(LocalDB)\MSSQLLocalDB" -Q "SELECT name FROM sys.databases WHERE name = 'TestDB';" | |
| - name: "Install PostgreSQL ODBC driver and server" | |
| if: ${{ matrix.test_env == 'postgres' }} | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| # The windows-2025 runner image ships PostgreSQL 17 pre-installed but | |
| # the `postgresql-x64-17` service refuses to start on this image (the | |
| # generic "Cannot start service" error suggests the service is | |
| # disabled or its data dir is not initialized). Disable it so it | |
| # cannot race with the chocolatey pg16 install for port 5432. | |
| Get-Service postgresql-x64-17 -ErrorAction SilentlyContinue | ForEach-Object { | |
| Stop-Service -Name $_.Name -Force -ErrorAction SilentlyContinue | |
| Set-Service -Name $_.Name -StartupType Disabled | |
| } | |
| choco install psqlodbc -y --no-progress | |
| choco install postgresql16 --params "/Password:Lightweight!Test42" -y --no-progress | |
| - name: "Wait for PostgreSQL and create test database" | |
| if: ${{ matrix.test_env == 'postgres' }} | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| # choco's postgresql16 package starts the service after install; this | |
| # is just defensive in case it didn't, and is scoped to pg16 only so | |
| # it cannot try to start the broken pg17 service on this image. | |
| $svc = Get-Service postgresql-x64-16 -ErrorAction SilentlyContinue | |
| if ($svc -and $svc.Status -ne 'Running') { Start-Service $svc } | |
| $env:PGPASSWORD = "Lightweight!Test42" | |
| $pgBin = "C:\Program Files\PostgreSQL\16\bin" | |
| # Wait until the server accepts connections (max ~30s). | |
| $deadline = (Get-Date).AddSeconds(30) | |
| while ((Get-Date) -lt $deadline) { | |
| & "$pgBin\pg_isready.exe" -h localhost -p 5432 -U postgres -t 3 | |
| if ($LASTEXITCODE -eq 0) { break } | |
| Start-Sleep -Seconds 2 | |
| } | |
| & "$pgBin\psql.exe" -U postgres -h localhost -c "CREATE DATABASE test" | |
| - name: "List installed ODBC drivers" | |
| shell: pwsh | |
| run: Get-OdbcDriver | Format-Table -AutoSize | |
| - name: "Create .test-env.yml" | |
| shell: pwsh | |
| run: | | |
| @" | |
| ODBC_CONNECTION_STRING: | |
| sqlite3: "Driver={SQLite3 ODBC Driver};Database=test.db" | |
| mssql: "Driver={ODBC Driver 17 for SQL Server};Server=(LocalDB)\\MSSQLLocalDB;Database=TestDB;Trusted_Connection=Yes;" | |
| postgres: "Driver={PostgreSQL Unicode};Server=localhost;Port=5432;Uid=postgres;Pwd=Lightweight!Test42;Database=test;LFConversion=0;BoolsAsChar=0" | |
| "@ | Out-File -FilePath .test-env.yml -Encoding utf8 | |
| - name: "Run SQL tests" | |
| run: ./install/bin/LightweightTest.exe --test-env=${{ matrix.test_env }} | |
| - name: "Run dbtool tests" | |
| shell: bash | |
| # PYTHONUNBUFFERED=1 surfaces the per-step `--- N. … ---` markers in real | |
| # time. Without it, Python buffers stdout under bash and CI sees nothing | |
| # until the script exits — making a hung dbtool invocation look like | |
| # "the whole step is silent" instead of pointing at the failing command. | |
| # DBTOOL_TRACE=1 turns on cheap stderr breadcrumbs in dbtool itself, | |
| # to localise where exactly a hung invocation is stuck (plugin load, | |
| # connection setup, query, etc.). The trace is gated on the env var | |
| # and adds nothing to normal runs. | |
| env: | |
| PYTHONUNBUFFERED: "1" | |
| DBTOOL_TRACE: "1" | |
| run: | | |
| set -ex | |
| python install/share/Lightweight/tests/test_dbtool.py \ | |
| --dbtool ./install/bin/dbtool.exe \ | |
| --plugins-dir ./install/share/Lightweight/tests/plugins \ | |
| --test-env ${{ matrix.test_env }} | |
| - name: "Capture LocalDB diagnostics on failure" | |
| if: ${{ failure() && matrix.test_env == 'mssql' }} | |
| shell: pwsh | |
| # Belt-and-braces: the Python-level capture in test_dbtool.py fires on | |
| # per-command timeout. This step covers the other failure modes | |
| # (non-zero dbtool exit, runner-level timeout, etc.) and is best-effort | |
| # so it never masks the original failure. | |
| run: | | |
| $ErrorActionPreference = 'Continue' | |
| sqlcmd -S "(LocalDB)\MSSQLLocalDB" -d TestDB -Q " | |
| SET NOCOUNT ON; | |
| SELECT session_id, blocking_session_id, wait_type, wait_resource, | |
| command, status, last_wait_type, | |
| CAST(text AS nvarchar(2000)) AS sql_text | |
| FROM sys.dm_exec_requests r | |
| OUTER APPLY sys.dm_exec_sql_text(r.sql_handle); | |
| SELECT request_session_id, resource_type, resource_associated_entity_id, | |
| request_mode, request_status FROM sys.dm_tran_locks; | |
| EXEC sp_who2; | |
| " | |
| # NOTE: A Linux-container Docker matrix on windows-2025 (matching the Linux | |
| # `dbms_test_matrix`) is desired for cross-OS driver/server coverage but is | |
| # not feasible on the current runner image: it ships Docker (Mirantis | |
| # runtime) for Windows containers only, with no Docker Desktop and no | |
| # in-WSL2 dockerd. Enabling it would require either Docker Desktop (license | |
| # blocker for commercial repos) or installing a WSL2 distro + dockerd per | |
| # job (3-10 min of brittle setup per matrix leg). The | |
| # `windows_mssql_drivers` job below substitutes a native SQL Server | |
| # Developer Edition install for this — it gives a real Windows SQL Server | |
| # service (TCP/IP on 1433, mixed-mode auth, separate process) that we can | |
| # exercise through every Windows-supported MSSQL ODBC driver. Tracked as | |
| # future work to also add the Linux-container approach once a runner image | |
| # supports it. | |
| windows_mssql_drivers: | |
| name: "Windows Tests (SQL Server, ${{ matrix.driver.label }})" | |
| runs-on: windows-2025 | |
| needs: [windows] | |
| # The 3 drivers run as parallel matrix legs (rather than sequential stages | |
| # inside one job) so a failure in one driver doesn't mask diagnostics from | |
| # the others, and so each leg appears as its own check on the PR. The | |
| # SQL Server install (~3-5 min) is the per-leg cost we pay for that | |
| # isolation; it is still cheaper than the alternative of bringing up a | |
| # Linux MSSQL Docker container on the Windows runner. | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| driver: | |
| - label: "ODBC Driver 17" | |
| test_env: "mssql_odbc17" | |
| driver_name: "ODBC Driver 17 for SQL Server" | |
| extra: ";TrustServerCertificate=Yes" | |
| - label: "ODBC Driver 18" | |
| test_env: "mssql_odbc18" | |
| driver_name: "ODBC Driver 18 for SQL Server" | |
| extra: ";TrustServerCertificate=Yes" | |
| steps: | |
| - name: "Download unit test binaries" | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: cl-debug-tests | |
| path: install | |
| - name: "Install Python YAML" | |
| shell: pwsh | |
| run: python -m pip install --disable-pip-version-check pyyaml | |
| - name: "Disable conflicting PostgreSQL services" | |
| shell: pwsh | |
| # Defensive: the windows-2025 image ships PostgreSQL 17 pre-installed. | |
| # It is not used here and we want to eliminate any chance of port | |
| # contention or unexpected service activity during SQL Server setup. | |
| run: | | |
| $ErrorActionPreference = 'Continue' | |
| Get-Service postgresql-x64-* -ErrorAction SilentlyContinue | ForEach-Object { | |
| Stop-Service -Name $_.Name -Force -ErrorAction SilentlyContinue | |
| Set-Service -Name $_.Name -StartupType Disabled | |
| } | |
| - name: "Install SQL Server (Developer Edition)" | |
| # The community chocolatey `sql-server-express` package hardcodes | |
| # /INSTANCENAME=SQLEXPRESS and silently drops --params, so it cannot | |
| # be coerced into a default-instance / TCP-1433 / SA-auth setup. The | |
| # `potatoqualitee/mssqlsuite` action direct-downloads the Microsoft | |
| # SQL Server 2022 Developer Edition bootstrapper and runs it with | |
| # /INSTANCENAME=MSSQLSERVER /TCPENABLED=1, then flips LoginMode=2 in | |
| # the registry and resets the SA password post-install — yielding | |
| # exactly what we need (localhost,1433 + SA auth). Developer Edition | |
| # is feature-identical to Enterprise and free for test use, so it is | |
| # a strictly more thorough "real MSSQL" target than Express. | |
| uses: potatoqualitee/mssqlsuite@v1.12 | |
| with: | |
| install: sqlengine | |
| version: 2022 | |
| sa-password: "Lightweight!Test42" | |
| show-log: true | |
| - name: "Install ODBC Driver 17 and 18" | |
| shell: pwsh | |
| # windows-2025 only guarantees the OLEDB drivers and the in-box | |
| # legacy "SQL Server" ODBC driver. ODBC Driver 17 and 18 (which are | |
| # distinct from OLEDB 17/18) are installed explicitly here. Version- | |
| # pinned package names — the unsuffixed `sqlserver-odbcdriver` | |
| # currently tracks Driver 18 and would silently swap to a future | |
| # major. The Get-OdbcDriver dump below verifies which drivers | |
| # actually registered. | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| choco install sqlserver-odbcdriver-17 -y --no-progress | |
| choco install sqlserver-odbcdriver-18 -y --no-progress | |
| - name: "List installed ODBC drivers" | |
| shell: pwsh | |
| run: Get-OdbcDriver | Format-Table -AutoSize | |
| - name: "Create LightweightTest database" | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| sqlcmd -S "localhost,1433" -U SA -P "Lightweight!Test42" -Q "CREATE DATABASE LightweightTest;" | |
| - name: "Create .test-env.yml" | |
| shell: pwsh | |
| # Sole entry matches matrix.driver.test_env so each leg only ever | |
| # talks to the driver under test (no cross-driver leakage if a future | |
| # test accidentally hardcodes a key). | |
| run: | | |
| @" | |
| ODBC_CONNECTION_STRING: | |
| ${{ matrix.driver.test_env }}: "Driver={${{ matrix.driver.driver_name }}};Server=localhost,1433;Database=LightweightTest;Uid=SA;Pwd=Lightweight!Test42${{ matrix.driver.extra }}" | |
| "@ | Out-File -FilePath .test-env.yml -Encoding utf8 | |
| - name: "Run SQL tests" | |
| run: ./install/bin/LightweightTest.exe --test-env=${{ matrix.driver.test_env }} | |
| - name: "Run dbtool tests" | |
| shell: bash | |
| env: | |
| PYTHONUNBUFFERED: "1" | |
| DBTOOL_TRACE: "1" | |
| run: | | |
| set -ex | |
| python install/share/Lightweight/tests/test_dbtool.py \ | |
| --dbtool ./install/bin/dbtool.exe \ | |
| --plugins-dir ./install/share/Lightweight/tests/plugins \ | |
| --test-env ${{ matrix.driver.test_env }} | |
| - name: "Capture SQL Server diagnostics on failure" | |
| if: ${{ failure() }} | |
| shell: pwsh | |
| # Best-effort post-mortem — same shape as the LocalDB diagnostics | |
| # block above so a failure here is debuggable from the workflow log | |
| # alone. Wrapped in Continue + try/catch so a sqlcmd failure here | |
| # cannot mask the actual test failure. | |
| run: | | |
| $ErrorActionPreference = 'Continue' | |
| try { | |
| sqlcmd -S "localhost,1433" -U SA -P "Lightweight!Test42" -d LightweightTest -Q " | |
| SET NOCOUNT ON; | |
| SELECT session_id, blocking_session_id, wait_type, wait_resource, | |
| command, status, last_wait_type, | |
| CAST(text AS nvarchar(2000)) AS sql_text | |
| FROM sys.dm_exec_requests r | |
| OUTER APPLY sys.dm_exec_sql_text(r.sql_handle); | |
| SELECT request_session_id, resource_type, resource_associated_entity_id, | |
| request_mode, request_status FROM sys.dm_tran_locks; | |
| EXEC sp_who2; | |
| " | |
| } catch { | |
| Write-Host "Diagnostics query failed: $_" | |
| } | |
| # }}} | |
| # {{{ macOS | |
| macos: | |
| # macOS coverage for the Homebrew-LLVM / libc++ toolchain, which differs in | |
| # non-obvious ways from the Linux libstdc++ and Windows MSVC STLs (e.g. | |
| # libc++ has no <stacktrace>, gates utc_clock behind its tz database, and | |
| # rejects std::char_traits<unsigned char>). GitHub's macOS runners cannot | |
| # run Docker, so only the natively-installable SQLite backend is exercised | |
| # here; MSSQL/PostgreSQL stay covered by the Linux/Windows matrices. | |
| name: "macOS (Homebrew LLVM, SQLite)" | |
| # Newest available runner; we don't target old macOS. (Doesn't relax libc++ | |
| # availability gates like float std::from_chars, which needs macOS 26.) | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Fetch tags | |
| # cmake/Version.cmake derives the project version from the latest `v*` | |
| # git tag; actions/checkout does a shallow clone without tags. | |
| run: git fetch --prune --unshallow --tags | |
| - name: ccache | |
| uses: hendrikmuhs/ccache-action@v1.2 | |
| with: | |
| key: "ccache-macos-llvm${{ env.CLANG_TOOLS_VERSION }}" | |
| - name: "Install dependencies (Homebrew)" | |
| # llvm@${{ env.CLANG_TOOLS_VERSION }} pins the same major Clang the rest | |
| # of the project targets, so libc++/C++23 behaviour matches local dev | |
| # (the runner's stock AppleClang would diverge under the warning set). | |
| run: | | |
| brew update | |
| brew install \ | |
| llvm@${{ env.CLANG_TOOLS_VERSION }} \ | |
| cmake ninja catch2 yaml-cpp libzip unixodbc sqliteodbc | |
| - name: "Register the SQLite3 ODBC driver" | |
| # Homebrew's sqliteodbc ships the driver dylib but does not register it | |
| # with unixODBC. Register BOTH names the test suite uses on non-Windows: | |
| # `SQLite3 ODBC Driver` (scripts/tests/.test-env.yml `sqlite3` key, used | |
| # by `LightweightTest --test-env=sqlite3`) and `SQLite3` (the default | |
| # string baked into the binary and into the DbToolIntegrationTest ctest, | |
| # see src/tests/CMakeLists.txt). One dylib, two stanzas. | |
| run: | | |
| set -ex | |
| SQLITE_ODBC="$(brew --prefix)/lib/libsqlite3odbc.dylib" | |
| test -f "$SQLITE_ODBC" | |
| { | |
| printf '[SQLite3 ODBC Driver]\nDescription=SQLite3 ODBC Driver\nDriver=%s\nSetup=%s\nThreading=2\n\n' \ | |
| "$SQLITE_ODBC" "$SQLITE_ODBC" | |
| printf '[SQLite3]\nDescription=SQLite3 ODBC Driver\nDriver=%s\nSetup=%s\nThreading=2\n' \ | |
| "$SQLITE_ODBC" "$SQLITE_ODBC" | |
| } > "$RUNNER_TEMP/sqlite3-odbc.ini" | |
| odbcinst -i -d -f "$RUNNER_TEMP/sqlite3-odbc.ini" | |
| odbcinst -q -d | |
| - name: "Configure" | |
| # Reuse the Darwin-capable clang-debug preset but disable the checks the | |
| # macOS leg should not re-run: clang-tidy and the sanitizers are already | |
| # covered by the Linux jobs, and PEDANTIC_COMPILER=OFF drops the | |
| # warning block + -Werror (which is gated on it). A dedicated -B dir | |
| # keeps this independent of the preset's own binaryDir. | |
| run: | | |
| set -ex | |
| LLVM="$(brew --prefix llvm@${{ env.CLANG_TOOLS_VERSION }})" | |
| cmake --preset clang-debug -B out/build/macos-ci \ | |
| -D CMAKE_CXX_COMPILER="$LLVM/bin/clang++" \ | |
| -D CMAKE_C_COMPILER="$LLVM/bin/clang" \ | |
| -D CMAKE_C_COMPILER_LAUNCHER=ccache \ | |
| -D CMAKE_CXX_COMPILER_LAUNCHER=ccache \ | |
| -D ENABLE_TIDY=OFF \ | |
| -D PEDANTIC_COMPILER=OFF \ | |
| -D PEDANTIC_COMPILER_WERROR=OFF \ | |
| -D ENABLE_SANITIZER_ADDRESS=OFF \ | |
| -D ENABLE_SANITIZER_UNDEFINED=OFF | |
| - name: "Build" | |
| run: cmake --build out/build/macos-ci --parallel "$(sysctl -n hw.ncpu)" | |
| - name: "Install Python YAML" | |
| # Needed by test_dbtool.py (and harmless for ctest); the macOS runner's | |
| # python is externally managed, so --break-system-packages is required. | |
| run: python3 -m pip install --break-system-packages --disable-pip-version-check pyyaml | |
| - name: "Run tests (SQLite via ctest)" | |
| # ctest runs both LightweightTest (default `DRIVER=SQLite3` connection) | |
| # and DbToolIntegrationTest (the test_dbtool.py suite, also `SQLite3`). | |
| env: | |
| PYTHONUNBUFFERED: "1" | |
| run: ctest --test-dir out/build/macos-ci --output-on-failure | |
| # }}} | |
| # {{{ Ubuntu build CC matrix | |
| ubuntu_build_cc_matrix: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| cxx: [23] | |
| build_type: ["RelWithDebInfo"] | |
| compiler: ["GCC 14", "Clang 19"] | |
| name: "Ubuntu Linux 24.04 (${{ matrix.compiler }}, C++${{ matrix.cxx }})" | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| id: "${{ matrix.compiler }} (C++${{ matrix.cxx }}, ${{ matrix.build_type }})" | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Fetch tags | |
| run: git fetch --prune --unshallow --tags | |
| - name: ccache | |
| uses: hendrikmuhs/ccache-action@v1.2 | |
| with: | |
| key: "ccache-ubuntu2404-${{ matrix.compiler }}-${{ matrix.cxx }}-${{ matrix.build_type }}" | |
| max-size: 256M | |
| - name: "update APT database" | |
| run: sudo apt -q update | |
| - name: "Set up output var: CC_VERSION" | |
| id: extract_matrix | |
| run: | | |
| CC_VERSION=$( echo "${{ matrix.compiler }}" | awk '{ print $2; }') | |
| echo "CC_VERSION=${CC_VERSION}" >> "$GITHUB_OUTPUT" | |
| - name: "install dependencies" | |
| run: sudo apt install -y cmake ninja-build catch2 unixodbc-dev sqlite3 libsqlite3-dev libsqliteodbc uuid-dev libyaml-cpp-dev libzip-dev | |
| - name: Install GCC | |
| if: ${{ startsWith(matrix.compiler, 'GCC') }} | |
| run: sudo apt install -y g++-${{ steps.extract_matrix.outputs.CC_VERSION }} | |
| - name: Install Clang | |
| if: ${{ startsWith(matrix.compiler, 'Clang') }} | |
| run: | | |
| wget https://apt.llvm.org/llvm.sh | |
| chmod +x llvm.sh | |
| sudo ./llvm.sh ${{ steps.extract_matrix.outputs.CC_VERSION }} | |
| # What about: libc++-dev libc++abi-dev | |
| sudo apt-get install -y \ | |
| clang-format-${{ steps.extract_matrix.outputs.CC_VERSION }} \ | |
| clang-${{ steps.extract_matrix.outputs.CC_VERSION }} | |
| - name: "cmake" | |
| run: | | |
| CC_NAME=$(echo "${{ matrix.compiler }}" | awk '{ print tolower($1); }') | |
| CC_VER=$( echo "${{ matrix.compiler }}" | awk '{ print $2; }') | |
| test "${{ matrix.compiler }}" = "GCC 8" && EXTRA_CMAKE_FLAGS="$EXTRA_CMAKE_FLAGS -DPEDANTIC_COMPILER_WERROR=ON" | |
| test "${CC_NAME}" = "gcc" && CC_EXE="g++" | |
| if [[ "${CC_NAME}" = "clang" ]]; then | |
| CC_EXE="clang++" | |
| # CMAKE_CXX_FLAGS="-stdlib=libc++" | |
| # CMAKE_EXE_LINKER_FLAGS="-stdlib=libc++ -lc++abi" | |
| # EXTRA_CMAKE_FLAGS="$EXTRA_CMAKE_FLAGS -DENABLE_TIDY=ON" | |
| # EXTRA_CMAKE_FLAGS="$EXTRA_CMAKE_FLAGS -DPEDANTIC_COMPILER_WERROR=OFF" | |
| fi | |
| cmake \ | |
| $EXTRA_CMAKE_FLAGS \ | |
| -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" \ | |
| -DCMAKE_CXX_STANDARD=${{ matrix.cxx }} \ | |
| -DCMAKE_CXX_COMPILER="${CC_EXE}-${CC_VER}" \ | |
| -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS}" \ | |
| -DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS}" \ | |
| -DCMAKE_INSTALL_PREFIX="/usr/local" \ | |
| -DPEDANTIC_COMPILER_WERROR=OFF \ | |
| -DLIGHTWEIGHT_BUILD_SHARED=ON \ | |
| --preset gcc-release | |
| - name: "build" | |
| run: cmake --build --preset gcc-release -- -j3 | |
| # NB: Don't run the tests here, as we want to run them later for each individual database | |
| # - name: "tests" | |
| # run: ctest --preset gcc-release | |
| # NB: Don't run valgrind test here, as we want to run them later for each individual database | |
| # - name: "Run tests through valgrind (without model tests)" | |
| # run: | | |
| # valgrind \ | |
| # --error-exitcode=1 \ | |
| # --leak-check=full \ | |
| # --leak-resolution=high \ | |
| # --num-callers=64 \ | |
| # out/build/gcc-release/src/tests/LightweightTest '~[model]' | |
| - name: "package tar.gz" | |
| run: | | |
| cpack --preset gcc-release | |
| cp out/package/gcc-release/Lightweight-*-Linux.tar.gz ./Lightweight-Linux-CI.tar.gz | |
| - name: "Move tests to root directory" | |
| run: mv out/build/gcc-release/src/tests/LightweightTest . | |
| - name: "Upload unit tests" | |
| if: ${{ matrix.compiler == 'GCC 14' && matrix.cxx == '23' }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ubuntu2404-tests | |
| path: | | |
| Lightweight-Linux-CI.tar.gz | |
| retention-days: 1 | |
| cpp26-reflection: | |
| name: "C++26 reflection implementation" | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v2 | |
| with: | |
| platforms: all | |
| - name: Set up Docker Buildx | |
| id: buildx | |
| uses: docker/setup-buildx-action@v2 | |
| with: | |
| version: latest | |
| - name: Build | |
| shell: bash | |
| run: | | |
| docker buildx build \ | |
| --progress=plain \ | |
| -f .github/Reflection.Dockerfile \ | |
| --load . --no-cache | |
| ubuntu_dbtool_gui: | |
| # Headless CI coverage for the Qt 6 dbtool-gui binary. Runs three test | |
| # layers under `QT_QPA_PLATFORM=offscreen` — Catch2 unit tests for | |
| # AppController, qmltestrunner suites for the Lightweight.Migrations QML | |
| # module, and a process smoke test against the real binary. No display | |
| # server is required. | |
| name: "dbtool-gui (Ubuntu, Qt 6.8, headless)" | |
| # ubuntu-24.04 ships Catch2 v3 (the test sources include the v3-only | |
| # `catch2/catch_session.hpp`); 22.04's `catch2` package is still v2. | |
| runs-on: ubuntu-24.04 | |
| env: | |
| QT_QPA_PLATFORM: offscreen | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Fetch tags | |
| # cmake/Version.cmake derives the project version from the latest | |
| # `v*` git tag; actions/checkout does a shallow clone without tags, so | |
| # unshallow + fetch tags here (matching ubuntu_build_cc_matrix). | |
| run: git fetch --prune --unshallow --tags | |
| - name: ccache | |
| uses: hendrikmuhs/ccache-action@v1.2 | |
| with: | |
| key: "ccache-ubuntu2404-dbtool-gui" | |
| - name: "update APT database" | |
| run: sudo apt -q update | |
| - name: "install build + ODBC dependencies" | |
| run: | | |
| sudo apt install -y \ | |
| cmake ninja-build catch2 \ | |
| unixodbc-dev libsqliteodbc \ | |
| uuid-dev libyaml-cpp-dev libzip-dev \ | |
| python3-yaml \ | |
| libgl1-mesa-dev libegl1 libxkbcommon0 libfontconfig1 | |
| - name: "install Clang 20" | |
| # clang-20 is not in the stock Ubuntu repositories — pull it from the | |
| # official LLVM apt source. | |
| run: | | |
| wget https://apt.llvm.org/llvm.sh | |
| chmod +x llvm.sh | |
| sudo ./llvm.sh 20 | |
| sudo apt-get install -y clang-20 | |
| - name: Install Qt 6.8 | |
| uses: jurplel/install-qt-action@v4 | |
| with: | |
| version: '6.8.0' | |
| cache: true | |
| # QtQml/QtQuick/QtQuickControls2 ship in the base desktop install — | |
| # they are NOT aqtinstall add-on modules, so listing `qtdeclarative` | |
| # here makes aqt fail its package-XML lookup. Only true add-ons go in | |
| # `modules`; qtshadertools provides the build-time `qsb` tooling. | |
| modules: 'qtshadertools' | |
| - name: "configure" | |
| run: | | |
| cmake -S . -B out/build/ci-gui \ | |
| -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=Debug \ | |
| -DCMAKE_CXX_COMPILER=clang++-20 \ | |
| -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ | |
| -DLIGHTWEIGHT_BUILD_GUI=ON \ | |
| -DLIGHTWEIGHT_BUILD_TESTS=ON \ | |
| -DPEDANTIC_COMPILER_WERROR=OFF | |
| - name: "build" | |
| run: cmake --build out/build/ci-gui --target dbtool-gui dbtool-gui-tests dbtool-gui-qmltest -- -j3 | |
| - name: "ctest (Catch2 + qmltestrunner + smoke)" | |
| run: ctest --test-dir out/build/ci-gui -L dbtool-gui --output-on-failure | |
| ddl2cpp: | |
| name: "ddl2cpp" | |
| runs-on: ubuntu-24.04 | |
| needs: [ubuntu_build_cc_matrix] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Fetch tags | |
| run: git fetch --prune --unshallow --tags | |
| - name: "Download binaries" | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ubuntu2404-tests | |
| - name: "Update APT database" | |
| run: sudo apt -q update | |
| - name: "Extract package" | |
| run: | | |
| sudo tar -xvf Lightweight-Linux-CI.tar.gz --strip-components=1 -C /usr/local | |
| - name: "Install dependencies" | |
| run: sudo apt install -y unixodbc-dev unixodbc libsqliteodbc odbcinst uuid-dev sqlite3 libyaml-cpp-dev libzip4 python3-yaml | |
| - name: "Install MS SQL ODBC driver" | |
| run: | | |
| curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc | |
| sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/20.04/prod.list)" | |
| sudo apt update | |
| sudo ACCEPT_EULA=y DEBIAN_FRONTEND=noninteractive apt install -y mssql-tools18 | |
| - name: "Start MS SQL Server 2022" | |
| run: python3 ./scripts/tests/docker-databases.py --start --wait mssql2022 | |
| - name: "Load Chinook data" | |
| run: python3 ./scripts/tests/docker-databases.py --load-sql ./src/examples/test_chinook/Chinook_Sqlite.sql mssql2022 | |
| - name: "Run ddl2cpp on Chinook db" | |
| run: | | |
| DDL2CPP=/usr/local/bin/ddl2cpp ./src/tools/test_chinook.sh --test-env=mssql2022 | |
| - name: "Install build dependencies" | |
| run: sudo apt install -y cmake ninja-build catch2 unixodbc-dev sqlite3 libsqlite3-dev libsqliteodbc uuid-dev libyaml-cpp-dev g++-14 libstdc++-14-dev libzip-dev | |
| - name: "Configure cmake" | |
| run: cmake --preset gcc-release -B build -D CMAKE_CXX_COMPILER=g++-14 -D LIGHTWEIGHT_BUILD_MODULES=ON | |
| - name: "Build chinook example" | |
| run: cmake --build build --target chinook | |
| - name: "Run chinook example" | |
| run: ./build/src/examples/test_chinook/chinook | |
| env: | |
| ODBC_CONNECTION_STRING: "Driver={ODBC Driver 18 for SQL Server};SERVER=localhost;PORT=1433;UID=SA;PWD=Lightweight!Test42;TrustServerCertificate=yes;DATABASE=LightweightTest" | |
| dbms_test_matrix: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - database: "SQLite3" | |
| test_env: "sqlite3" | |
| docker_db: "" | |
| - database: "MS SQL Server 2017" | |
| test_env: "mssql2017" | |
| docker_db: "mssql2017" | |
| - database: "MS SQL Server 2019" | |
| test_env: "mssql2019" | |
| docker_db: "mssql2019" | |
| - database: "MS SQL Server 2022" | |
| test_env: "mssql2022" | |
| docker_db: "mssql2022" | |
| - database: "MS SQL Server 2025" | |
| test_env: "mssql2025" | |
| docker_db: "mssql2025" | |
| - database: "PostgreSQL" | |
| test_env: "postgres" | |
| docker_db: "postgres" | |
| name: "Tests (${{ matrix.database }})" | |
| runs-on: ubuntu-24.04 | |
| needs: [ubuntu_build_cc_matrix] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: "Download unit test binaries" | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ubuntu2404-tests | |
| - name: "Extract package" | |
| run: | | |
| sudo tar -xvf Lightweight-Linux-CI.tar.gz --strip-components=1 -C /usr/local | |
| - name: "Update APT database" | |
| run: sudo apt -q update | |
| - name: "Install common dependencies" | |
| run: sudo apt install -y unixodbc odbcinst libuuid1 valgrind libyaml-cpp-dev libzip4 | |
| - name: "Install SQLite3 ODBC driver" | |
| if: matrix.database == 'SQLite3' | |
| # On Ubuntu, libsqliteodbc registers itself in /etc/odbcinst.ini under | |
| # `[SQLite3]`; on Windows, the choco-installed driver is `SQLite3 ODBC | |
| # Driver`. We rename the Linux entry so the same .test-env.yml string | |
| # works on both platforms. | |
| run: | | |
| sudo apt install -y libsqlite3-dev libsqliteodbc sqlite3 | |
| sudo sed -i 's/^\[SQLite3\]$/[SQLite3 ODBC Driver]/' /etc/odbcinst.ini | |
| - name: "Install MS SQL ODBC drivers (17 + 18)" | |
| if: startsWith(matrix.database, 'MS SQL') | |
| # mssql-tools18 pulls in msodbcsql18; install msodbcsql17 alongside so | |
| # the mssql2017 / mssql2025 legs can also exercise Driver 17 against | |
| # the same server (see the second "Run SQL tests (ODBC Driver 17)" | |
| # step below). | |
| run: | | |
| curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc | |
| sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/20.04/prod.list)" | |
| sudo apt update | |
| sudo ACCEPT_EULA=y DEBIAN_FRONTEND=noninteractive apt install -y msodbcsql17 mssql-tools18 | |
| - name: "Install PostgreSQL ODBC driver" | |
| if: matrix.database == 'PostgreSQL' | |
| run: sudo apt install -y odbc-postgresql | |
| - name: "Start Docker database" | |
| if: matrix.docker_db != '' | |
| run: python3 ./scripts/tests/docker-databases.py --start --wait ${{ matrix.docker_db }} | |
| - name: "Inspect dependencies" | |
| run: ldd /usr/local/bin/LightweightTest | |
| - name: "Run SQL tests (ODBC Driver 18)" | |
| run: | | |
| set -ex | |
| if [[ "${{ matrix.database }}" = "SQLite3" ]]; then | |
| CMD_PREFIX="valgrind --leak-check=full --leak-resolution=high --num-callers=64 --error-exitcode=1" | |
| fi | |
| $CMD_PREFIX LightweightTest --test-env=${{ matrix.test_env }} | |
| - name: "Run dbtool tests (ODBC Driver 18)" | |
| env: | |
| PYTHONUNBUFFERED: "1" | |
| run: | | |
| set -ex | |
| python3 /usr/local/share/Lightweight/tests/test_dbtool.py \ | |
| --dbtool /usr/local/bin/dbtool \ | |
| --plugins-dir /usr/local/share/Lightweight/tests/plugins \ | |
| --test-env ${{ matrix.test_env }} | |
| # Re-run the suite against the oldest + newest MSSQL versions through | |
| # ODBC Driver 17, against the same server instance. Catches regressions | |
| # that depend on driver-side behaviour (Unicode handling, datetime | |
| # binding, batch row counts) without doubling the matrix leg count. | |
| # `if: always()` is intentional so a Driver 18 failure still surfaces | |
| # whether Driver 17 sees the same problem. | |
| - name: "Run SQL tests (ODBC Driver 17)" | |
| if: ${{ always() && (matrix.test_env == 'mssql2017' || matrix.test_env == 'mssql2025') }} | |
| run: | | |
| set -ex | |
| LightweightTest --test-env=${{ matrix.test_env }}_odbc17 | |
| - name: "Run dbtool tests (ODBC Driver 17)" | |
| if: ${{ always() && (matrix.test_env == 'mssql2017' || matrix.test_env == 'mssql2025') }} | |
| env: | |
| PYTHONUNBUFFERED: "1" | |
| run: | | |
| set -ex | |
| python3 /usr/local/share/Lightweight/tests/test_dbtool.py \ | |
| --dbtool /usr/local/bin/dbtool \ | |
| --plugins-dir /usr/local/share/Lightweight/tests/plugins \ | |
| --test-env ${{ matrix.test_env }}_odbc17 | |
| - name: "Capture container log on failure" | |
| if: failure() && matrix.docker_db != '' | |
| run: | | |
| case "${{ matrix.docker_db }}" in | |
| mssql2017) container=sql2017 ;; | |
| mssql2019) container=sql2019 ;; | |
| mssql2022) container=sql2022 ;; | |
| mssql2025) container=sql2025 ;; | |
| postgres) container=postgres-16.4 ;; | |
| *) container="" ;; | |
| esac | |
| if [ -n "$container" ]; then | |
| echo "::group::docker logs $container (last 200 lines)" | |
| docker logs "$container" 2>&1 | tail -n 200 || true | |
| echo "::endgroup::" | |
| fi | |
| # }}} | |
| # {{{ Sanitizers | |
| sanitizers: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| sanitizer: ["asan-ubsan", "tsan"] | |
| name: "Sanitizers (${{ matrix.sanitizer }})" | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Fetch tags | |
| run: git fetch --prune --unshallow --tags | |
| - name: ccache | |
| uses: hendrikmuhs/ccache-action@v1.2 | |
| with: | |
| key: "ccache-ubuntu2404-clang-${{ matrix.sanitizer }}" | |
| max-size: 256M | |
| - name: "update APT database" | |
| run: sudo apt -q update | |
| - name: Install Clang | |
| run: | | |
| wget https://apt.llvm.org/llvm.sh | |
| chmod +x llvm.sh | |
| sudo ./llvm.sh ${{ env.CLANG_TOOLS_VERSION }} | |
| - name: "install dependencies" | |
| # Rename the libsqliteodbc driver section to match the Windows driver | |
| # name so the shared .test-env.yml works on both platforms. | |
| run: | | |
| sudo apt install -y cmake ninja-build catch2 unixodbc-dev sqlite3 libsqlite3-dev libsqliteodbc uuid-dev libyaml-cpp-dev libzip-dev | |
| sudo sed -i 's/^\[SQLite3\]$/[SQLite3 ODBC Driver]/' /etc/odbcinst.ini | |
| - name: "cmake" | |
| run: | | |
| cmake --preset clang-${{ matrix.sanitizer }} \ | |
| -D CMAKE_CXX_COMPILER=clang++-${{ env.CLANG_TOOLS_VERSION }} \ | |
| -D CMAKE_C_COMPILER=clang-${{ env.CLANG_TOOLS_VERSION }} | |
| - name: "build" | |
| run: cmake --build --preset clang-${{ matrix.sanitizer }} -- -j$(nproc) | |
| - name: "Run tests with ${{ matrix.sanitizer }}" | |
| env: | |
| ASAN_OPTIONS: "detect_leaks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1" | |
| UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=1:suppressions=${{ github.workspace }}/.github/ubsan.suppressions" | |
| TSAN_OPTIONS: "second_deadlock_stack=1" | |
| run: | | |
| ./out/build/clang-${{ matrix.sanitizer }}/src/tests/LightweightTest --test-env=sqlite3 | |
| # }}} | |
| # {{{ Coverage | |
| coverage: | |
| name: "Code coverage" | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Fetch tags | |
| run: git fetch --prune --unshallow --tags | |
| - name: ccache | |
| uses: hendrikmuhs/ccache-action@v1.2 | |
| with: | |
| key: "ccache-ubuntu2404-clang-coverage" | |
| max-size: 256M | |
| - name: "update APT database" | |
| run: sudo apt -q update | |
| - name: Install Clang | |
| run: | | |
| wget https://apt.llvm.org/llvm.sh | |
| chmod +x llvm.sh | |
| sudo ./llvm.sh ${{ env.CLANG_TOOLS_VERSION }} | |
| - name: "install dependencies" | |
| # Rename the libsqliteodbc driver section to match the Windows driver | |
| # name so the shared .test-env.yml works on both platforms. | |
| run: | | |
| sudo apt install -y cmake ninja-build catch2 unixodbc-dev sqlite3 libsqlite3-dev libsqliteodbc uuid-dev libyaml-cpp-dev libzip-dev lcov odbc-postgresql python3-yaml | |
| sudo sed -i 's/^\[SQLite3\]$/[SQLite3 ODBC Driver]/' /etc/odbcinst.ini | |
| - name: "Install MS SQL ODBC drivers (17 + 18)" | |
| # Both driver generations, so coverage includes the Driver 17 and | |
| # Driver 18 code paths (mirrors dbms_test_matrix). | |
| run: | | |
| curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc | |
| sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/20.04/prod.list)" | |
| sudo apt update | |
| sudo ACCEPT_EULA=y DEBIAN_FRONTEND=noninteractive apt install -y msodbcsql17 mssql-tools18 | |
| - name: "Start Docker databases" | |
| run: python3 ./scripts/tests/docker-databases.py --start --wait mssql2022 mssql2017 postgres | |
| - name: "cmake" | |
| run: | | |
| cmake --preset clang-coverage \ | |
| -D CMAKE_CXX_COMPILER=clang++-${{ env.CLANG_TOOLS_VERSION }} \ | |
| -D CMAKE_C_COMPILER=clang-${{ env.CLANG_TOOLS_VERSION }} | |
| - name: "build" | |
| run: cmake --build --preset clang-coverage -- -j$(nproc) | |
| # Each coverage-<env> target (cmake/Coverage.cmake) zeroes the gcov | |
| # counters, runs the suite against one database/driver combination, and | |
| # captures a per-environment lcov tracefile. Every tracefile is uploaded | |
| # to Codecov under its own flag; Codecov merges all uploads of a commit | |
| # into the combined report, so the headline number is the union across | |
| # databases and ODBC driver versions, while the flags break coverage | |
| # down per environment. The env/driver combinations mirror ones already | |
| # validated by dbms_test_matrix: mssql2022 via ODBC Driver 18, mssql2017 | |
| # via ODBC Driver 17. | |
| - name: "Run tests and generate lcov report (SQLite3)" | |
| run: cmake --build --preset clang-coverage --target coverage-sqlite3 | |
| - name: "Run tests and generate lcov report (PostgreSQL)" | |
| run: cmake --build --preset clang-coverage --target coverage-postgres | |
| - name: "Run tests and generate lcov report (MSSQL 2022, ODBC Driver 18)" | |
| run: cmake --build --preset clang-coverage --target coverage-mssql2022 | |
| - name: "Run tests and generate lcov report (MSSQL 2017, ODBC Driver 17)" | |
| run: cmake --build --preset clang-coverage --target coverage-mssql2017_odbc17 | |
| # Guards the blind spot that the coverage *percentage* structurally cannot catch: gcov emits | |
| # records per template instantiation, so a template nothing instantiates contributes no lines | |
| # at all rather than counting as uncovered. Its absence therefore never lowers the headline | |
| # number. This ratchets the instrumented-line count per library header instead, so a template | |
| # that stops being instantiated fails the build. | |
| # | |
| # Enforcing: deliberately no `continue-on-error`, because a step that cannot fail is | |
| # indistinguishable from no gate at all. A regression below the tolerance now reds the build. | |
| # | |
| # Bootstrapping: the baseline must come from a real lcov run, which only this job performs, | |
| # so `.instantiation-coverage-baseline.json` is not committed yet and this first run merely | |
| # prints the numbers it would contain. To arm the ratchet, copy those numbers into the | |
| # baseline (`--update-baseline` against all four tracefiles) and commit it; from then on the | |
| # step compares against it. Add `--require-baseline` here once it is committed, so a deleted | |
| # baseline fails instead of silently disarming the check. | |
| - name: "Check template instantiation coverage" | |
| run: > | |
| python3 scripts/check-instantiation-coverage.py | |
| --tracefile out/build/clang-coverage/coverage/sqlite3.info | |
| --tracefile out/build/clang-coverage/coverage/postgres.info | |
| --tracefile out/build/clang-coverage/coverage/mssql2022.info | |
| --tracefile out/build/clang-coverage/coverage/mssql2017_odbc17.info | |
| - name: "Upload SQLite3 coverage to Codecov" | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ./out/build/clang-coverage/coverage/sqlite3.info | |
| flags: sqlite3 | |
| fail_ci_if_error: false | |
| - name: "Upload PostgreSQL coverage to Codecov" | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ./out/build/clang-coverage/coverage/postgres.info | |
| flags: postgres | |
| fail_ci_if_error: false | |
| - name: "Upload MSSQL 2022 (Driver 18) coverage to Codecov" | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ./out/build/clang-coverage/coverage/mssql2022.info | |
| flags: mssql2022_odbc18 | |
| fail_ci_if_error: false | |
| - name: "Upload MSSQL 2017 (Driver 17) coverage to Codecov" | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ./out/build/clang-coverage/coverage/mssql2017_odbc17.info | |
| flags: mssql2017_odbc17 | |
| fail_ci_if_error: false | |
| # }}} |