Add CTest coverage reporting
Some checks failed
libakgl CI Build / cmake_build (push) Failing after 19s
libakgl CI Build / mutation_test (push) Failing after 16s

Instrument libakgl in opt-in coverage builds, use CTest fixtures to reset counters and emit Cobertura XML and detailed HTML reports, and upload those reports from Gitea CI. Document the local coverage workflow for contributors.

Co-authored-by: Codex (GPT-5) <noreply@openai.com>
This commit is contained in:
2026-07-30 01:25:26 -04:00
parent 549b27d3eb
commit ff88f48fa2
3 changed files with 60 additions and 3 deletions

View File

@@ -14,7 +14,7 @@ jobs:
run: | run: |
sudo apt-get update -y sudo apt-get update -y
sudo apt-get install -y \ sudo apt-get install -y \
cmake doxygen gcc pkg-config \ cmake doxygen gcc gcovr pkg-config \
libasound2-dev libfreetype-dev libharfbuzz-dev \ libasound2-dev libfreetype-dev libharfbuzz-dev \
libpng-dev libtiff-dev libwebp-dev \ libpng-dev libtiff-dev libwebp-dev \
libudev-dev libx11-dev libxcursor-dev libxext-dev \ libudev-dev libx11-dev libxcursor-dev libxext-dev \
@@ -22,7 +22,9 @@ jobs:
libxss-dev libxtst-dev libxss-dev libxtst-dev
- name: Configure and build - name: Configure and build
run: | run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DAKGL_COVERAGE=ON
cmake --build build --parallel cmake --build build --parallel
- name: Build API documentation - name: Build API documentation
run: doxygen Doxyfile run: doxygen Doxyfile
@@ -43,6 +45,13 @@ jobs:
detailed_summary: true detailed_summary: true
include_passed: true include_passed: true
fail_on_failure: 'true' fail_on_failure: 'true'
- name: Upload coverage reports
if: always()
uses: actions/upload-artifact@v4
with:
name: code-coverage
path: build/coverage/
if-no-files-found: warn
mutation_test: mutation_test:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -28,6 +28,8 @@ Run one test while iterating, for example `ctest --test-dir build -R sprite --ou
Run mutation testing with `cmake --build build --target mutation`. For a quick smoke run, use `scripts/mutation_test.py --target src/tilemap.c --max-mutants 10`; the harness mutates only a scratch copy and excludes the intentionally failing character test. Run mutation testing with `cmake --build build --target mutation`. For a quick smoke run, use `scripts/mutation_test.py --target src/tilemap.c --max-mutants 10`; the harness mutates only a scratch copy and excludes the intentionally failing character test.
Generate HTML and Cobertura coverage reports with `cmake -S . -B build-coverage -DAKGL_COVERAGE=ON -DCMAKE_BUILD_TYPE=Debug`, then build and run CTest. Reports are written to `build-coverage/coverage/`; this mode requires `gcovr` and GCC or Clang.
## Coding Style & Naming Conventions ## Coding Style & Naming Conventions
Follow the surrounding C style: braces on the next line for function bodies, spaces inside control-flow parentheses, and short, focused functions. Preserve the indentation of the file being edited; older files contain both spaces and tabs. Public symbols use the `akgl_` prefix, public types use `akgl_TypeName`, and constants/macros use `AKGL_UPPER_SNAKE_CASE`. Name matching header/source pairs by feature, such as `include/akgl/sprite.h` and `src/sprite.c`. No repository-wide formatter or linter is configured, so avoid unrelated formatting churn. Follow the surrounding C style: braces on the next line for function bodies, spaces inside control-flow parentheses, and short, focused functions. Preserve the indentation of the file being edited; older files contain both spaces and tabs. Public symbols use the `akgl_` prefix, public types use `akgl_TypeName`, and constants/macros use `AKGL_UPPER_SNAKE_CASE`. Name matching header/source pairs by feature, such as `include/akgl/sprite.h` and `src/sprite.c`. No repository-wide formatter or linter is configured, so avoid unrelated formatting churn.
@@ -39,7 +41,7 @@ Follow the surrounding C style: braces on the next line for function bodies, spa
## Testing Guidelines ## Testing Guidelines
Tests use simple executable return codes and are registered through CTest in `CMakeLists.txt`; there is no declared coverage threshold. Add focused tests as `tests/<feature>.c`, create a matching `test_<feature>` target, and register it with `add_test`. Put reusable fixtures in `tests/assets/` and keep paths compatible with tests launched from the build tree. Tests use simple executable return codes and are registered through CTest in `CMakeLists.txt`; there is no declared coverage threshold. Add focused tests as `tests/<feature>.c`, create a matching `test_<feature>` target, and register it with `add_test`. Put reusable fixtures in `tests/assets/` and keep paths compatible with tests launched from the build tree. Coverage mode wraps the suite in a CTest fixture so counters are reset before tests and reports are generated afterward.
## Commit & Pull Request Guidelines ## Commit & Pull Request Guidelines

View File

@@ -2,6 +2,14 @@ cmake_minimum_required(VERSION 3.10)
project(akgl LANGUAGES C) project(akgl LANGUAGES C)
include(CTest) include(CTest)
option(AKGL_COVERAGE "Instrument libakgl and generate coverage reports with CTest" OFF)
if(AKGL_COVERAGE)
if(NOT CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
message(FATAL_ERROR "AKGL_COVERAGE requires GCC or Clang")
endif()
find_program(GCOVR_EXECUTABLE gcovr REQUIRED)
endif()
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
@@ -141,6 +149,44 @@ target_include_directories(akgl PUBLIC
deps/semver/ deps/semver/
) )
if(AKGL_COVERAGE)
target_compile_options(akgl PRIVATE --coverage -O0 -g)
target_link_options(akgl PRIVATE --coverage)
set(AKGL_COVERAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/coverage")
file(MAKE_DIRECTORY "${AKGL_COVERAGE_DIR}")
add_test(
NAME coverage_reset
COMMAND ${GCOVR_EXECUTABLE}
--root "${CMAKE_CURRENT_SOURCE_DIR}"
--object-directory "${CMAKE_CURRENT_BINARY_DIR}"
--delete
)
set_tests_properties(coverage_reset PROPERTIES FIXTURES_SETUP akgl_coverage)
set_tests_properties(
actor bitmasks character registry sprite staticstring tilemap util semver_unit
PROPERTIES FIXTURES_REQUIRED akgl_coverage
)
add_test(
NAME coverage_report
COMMAND ${GCOVR_EXECUTABLE}
--root "${CMAKE_CURRENT_SOURCE_DIR}"
--object-directory "${CMAKE_CURRENT_BINARY_DIR}"
--filter "${CMAKE_CURRENT_SOURCE_DIR}/src/"
--xml-pretty
--xml "${AKGL_COVERAGE_DIR}/coverage.xml"
--html-details "${AKGL_COVERAGE_DIR}/index.html"
)
set_tests_properties(
coverage_report
PROPERTIES
FIXTURES_CLEANUP akgl_coverage
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
)
endif()
target_link_libraries(akgl target_link_libraries(akgl
PUBLIC PUBLIC
SDL3::SDL3 SDL3::SDL3