Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e0f4fc8d0 | |||
| cd19cc14c0 |
@@ -2,6 +2,7 @@
|
|||||||
build
|
build
|
||||||
build-*
|
build-*
|
||||||
cmake-build-*
|
cmake-build-*
|
||||||
|
coverage
|
||||||
|
|
||||||
# Editors
|
# Editors
|
||||||
.vscode
|
.vscode
|
||||||
|
|||||||
@@ -12,12 +12,44 @@
|
|||||||
|
|
||||||
### Commands
|
### Commands
|
||||||
|
|
||||||
|
Configure (default):
|
||||||
```sh
|
```sh
|
||||||
cmake -S . -B build -G Ninja
|
cmake -S . -B build -G Ninja
|
||||||
ninja -C build # build
|
```
|
||||||
ninja -C build test # run tests
|
|
||||||
./build/main # run (Linux/macOS)
|
Configure with coverage:
|
||||||
./build/main.exe # run (Windows)
|
```sh
|
||||||
|
cmake -S . -B build-cov -G Ninja -DENABLE_COVERAGE=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
Build:
|
||||||
|
```sh
|
||||||
|
ninja -C build
|
||||||
|
```
|
||||||
|
|
||||||
|
Run tests — full Unity output, colored:
|
||||||
|
```sh
|
||||||
|
ninja -C build check
|
||||||
|
```
|
||||||
|
|
||||||
|
Run tests — CTest summary only:
|
||||||
|
```sh
|
||||||
|
ninja -C build test
|
||||||
|
```
|
||||||
|
|
||||||
|
Run tests and generate coverage HTML:
|
||||||
|
```sh
|
||||||
|
ninja -C build-cov coverage
|
||||||
|
```
|
||||||
|
|
||||||
|
Run (Linux/macOS):
|
||||||
|
```sh
|
||||||
|
./build/main
|
||||||
|
```
|
||||||
|
|
||||||
|
Run (Windows):
|
||||||
|
```sh
|
||||||
|
./build/main.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
@@ -113,6 +145,15 @@ in HH:MM:SS.mmm format, updating every 10ms with color output.
|
|||||||
`-` or numbered lists, fenced code blocks with language hints
|
`-` or numbered lists, fenced code blocks with language hints
|
||||||
(```` ```cpp ````, ```` ```sh ````).
|
(```` ```cpp ````, ```` ```sh ````).
|
||||||
- Keep examples concise, up-to-date, and self-documenting.
|
- Keep examples concise, up-to-date, and self-documenting.
|
||||||
|
- Each shell command gets its own fenced code block — do **not** combine
|
||||||
|
multiple commands into one block. Precede each block with a short
|
||||||
|
plain-text label describing what the command does:
|
||||||
|
|
||||||
|
Setup build:
|
||||||
|
```sh
|
||||||
|
cmake -S . -B build -G Ninja
|
||||||
|
```
|
||||||
|
|
||||||
- This file (`AGENTS.md`) follows its own rules.
|
- This file (`AGENTS.md`) follows its own rules.
|
||||||
|
|
||||||
## Source Layout
|
## Source Layout
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/deps")
|
|||||||
include(Platform)
|
include(Platform)
|
||||||
include(Flags)
|
include(Flags)
|
||||||
|
|
||||||
|
include(Coverage)
|
||||||
|
|
||||||
# Example Library
|
# Example Library
|
||||||
add_subdirectory(ctdd)
|
add_subdirectory(ctdd)
|
||||||
|
|
||||||
|
|||||||
@@ -10,40 +10,74 @@ manual installation required beyond the tools listed below.
|
|||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
| Tool | Purpose |
|
| Tool | Purpose |
|
||||||
| ------------------- | --------------------- |
|
| ------------ | ----------------------------------------------------- |
|
||||||
| CMake ≥ 3.21 | Build system |
|
| CMake ≥ 3.21 | Build system |
|
||||||
| Ninja | Build backend |
|
| Ninja | Build backend |
|
||||||
| C23 compiler | GCC 14+, Clang 18+ |
|
| C23 compiler | GCC 14+, Clang 18+ |
|
||||||
| Ruby ≥ 3.0 | CMock mock generation |
|
| Ruby ≥ 3.0 | CMock mock generation |
|
||||||
|
| gcovr ≥ 6.0 | Coverage reports — optional (`uv tool install gcovr`) |
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
|
Configure:
|
||||||
```sh
|
```sh
|
||||||
cmake -S . -B build -G Ninja
|
cmake -S . -B build -G Ninja
|
||||||
|
```
|
||||||
|
|
||||||
|
Build:
|
||||||
|
```sh
|
||||||
ninja -C build
|
ninja -C build
|
||||||
```
|
```
|
||||||
|
|
||||||
## Test
|
## Test
|
||||||
|
|
||||||
|
Full Unity output with colors:
|
||||||
```sh
|
```sh
|
||||||
ninja -C build test # summary output
|
ninja -C build check
|
||||||
ctest --test-dir build -V # verbose (shows each test name)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Run a single suite directly for the clearest output:
|
CTest summary only:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./build/tests/test_str.exe
|
ninja -C build test
|
||||||
./build/tests/test_report.exe
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`check` builds all suites and runs CTest with `--output-on-failure`,
|
||||||
|
so assertion-level detail appears on any failure without running
|
||||||
|
binaries by hand.
|
||||||
|
|
||||||
|
## Coverage
|
||||||
|
|
||||||
|
Configure with coverage instrumentation:
|
||||||
|
```sh
|
||||||
|
cmake -S . -B build-cov -G Ninja -DENABLE_COVERAGE=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
Generate the HTML report:
|
||||||
|
```sh
|
||||||
|
ninja -C build-cov coverage
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `build-cov/coverage/index.html` in a browser to view results.
|
||||||
|
|
||||||
|
Only `ctdd/` source files are measured — Unity, CMock, and generated
|
||||||
|
mock files are excluded. Requires GCC or Clang with gcov support, and
|
||||||
|
`gcovr` on `PATH`.
|
||||||
|
|
||||||
|
> **Windows note:** requires GCC (e.g. `scoop install gcc`) or a Clang
|
||||||
|
> build that includes compiler-rt. A custom Clang without compiler-rt
|
||||||
|
> will fail at link time.
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
|
Windows:
|
||||||
```sh
|
```sh
|
||||||
./build/main.exe # Windows
|
./build/main.exe
|
||||||
./build/main # Linux / macOS
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Linux / macOS:
|
||||||
|
```sh
|
||||||
|
./build/main
|
||||||
|
```
|
||||||
|
|
||||||
## Adding a new module (TDD workflow)
|
## Adding a new module (TDD workflow)
|
||||||
|
|
||||||
@@ -84,6 +118,7 @@ target_include_directories(test_counter PRIVATE "${CMAKE_SOURCE_DIR}")
|
|||||||
target_link_libraries(test_counter PRIVATE ctdd_counter Unity::Unity)
|
target_link_libraries(test_counter PRIVATE ctdd_counter Unity::Unity)
|
||||||
target_compile_features(test_counter PRIVATE c_std_23)
|
target_compile_features(test_counter PRIVATE c_std_23)
|
||||||
add_test(NAME test_counter COMMAND test_counter)
|
add_test(NAME test_counter COMMAND test_counter)
|
||||||
|
list(APPEND TEST_TARGETS test_counter)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Add a stub, confirm RED, then implement GREEN
|
### 4. Add a stub, confirm RED, then implement GREEN
|
||||||
|
|||||||
Vendored
+46
@@ -0,0 +1,46 @@
|
|||||||
|
# ==============================================================================
|
||||||
|
# Coverage
|
||||||
|
# ==============================================================================
|
||||||
|
# gcov-based coverage via --coverage, reported by gcovr.
|
||||||
|
# Works with GCC and Clang on Linux and macOS out of the box.
|
||||||
|
# Windows requires GCC (e.g. MinGW via scoop install gcc) or a Clang build
|
||||||
|
# that includes compiler-rt (clang_rt.profile).
|
||||||
|
#
|
||||||
|
# Requires: gcovr on PATH (install via: uv tool install gcovr)
|
||||||
|
# Usage: cmake -DENABLE_COVERAGE=ON ... then ninja coverage
|
||||||
|
# Report: build/coverage/index.html
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
option(ENABLE_COVERAGE "Build with coverage instrumentation" OFF)
|
||||||
|
|
||||||
|
if (ENABLE_COVERAGE)
|
||||||
|
if (NOT CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
|
message(FATAL_ERROR "ENABLE_COVERAGE requires GCC or Clang")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_program(GCOVR_EXE gcovr REQUIRED)
|
||||||
|
|
||||||
|
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||||
|
find_program(LLVM_COV_EXE llvm-cov REQUIRED)
|
||||||
|
# gcovr needs a single-token gcov executable. Wrap llvm-cov gcov in a
|
||||||
|
# script placed in the build dir (guaranteed no spaces in path).
|
||||||
|
if (WIN32)
|
||||||
|
set(GCOV_EXECUTABLE "${CMAKE_BINARY_DIR}/llvm-gcov.bat")
|
||||||
|
file(WRITE "${GCOV_EXECUTABLE}" "@echo off\r\n\"${LLVM_COV_EXE}\" gcov %*\r\n")
|
||||||
|
else()
|
||||||
|
set(GCOV_EXECUTABLE "${CMAKE_BINARY_DIR}/llvm-gcov.sh")
|
||||||
|
file(WRITE "${GCOV_EXECUTABLE}" "#!/bin/sh\nexec \"${LLVM_COV_EXE}\" gcov \"$@\"\n")
|
||||||
|
file(CHMOD "${GCOV_EXECUTABLE}"
|
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||||
|
GROUP_READ GROUP_EXECUTE
|
||||||
|
WORLD_READ WORLD_EXECUTE)
|
||||||
|
endif()
|
||||||
|
message(STATUS "Coverage: enabled (gcovr: ${GCOVR_EXE}, gcov: ${LLVM_COV_EXE} gcov)")
|
||||||
|
else()
|
||||||
|
set(GCOV_EXECUTABLE "gcov")
|
||||||
|
message(STATUS "Coverage: enabled (gcovr: ${GCOVR_EXE})")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_compile_options(--coverage -O0 -g)
|
||||||
|
add_link_options(--coverage)
|
||||||
|
endif()
|
||||||
Vendored
+7
@@ -55,4 +55,11 @@ if (Unity_INCLUDE_DIR AND TARGET unity)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (TARGET unity)
|
||||||
|
target_compile_definitions(unity PUBLIC
|
||||||
|
UNITY_OUTPUT_COLOR
|
||||||
|
UNITY_INCLUDE_PRINT_FORMATTED
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(UNITY_LICENSE_FILE "${unity_SOURCE_DIR}/LICENSE.txt" CACHE FILEPATH "Path to Unity license file")
|
set(UNITY_LICENSE_FILE "${unity_SOURCE_DIR}/LICENSE.txt" CACHE FILEPATH "Path to Unity license file")
|
||||||
|
|||||||
@@ -28,12 +28,15 @@ function(cmock_generate_mock target header)
|
|||||||
target_include_directories("${target}" PRIVATE "${MOCK_GEN_DIR}" "${header_dir}")
|
target_include_directories("${target}" PRIVATE "${MOCK_GEN_DIR}" "${header_dir}")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
set(TEST_TARGETS "")
|
||||||
|
|
||||||
# str tests — pure functions, no mock needed
|
# str tests — pure functions, no mock needed
|
||||||
add_executable(test_str test_str.c)
|
add_executable(test_str test_str.c)
|
||||||
target_include_directories(test_str PRIVATE "${CMAKE_SOURCE_DIR}")
|
target_include_directories(test_str PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||||
target_link_libraries(test_str PRIVATE ctdd_str Unity::Unity)
|
target_link_libraries(test_str PRIVATE ctdd_str Unity::Unity)
|
||||||
target_compile_features(test_str PRIVATE c_std_23)
|
target_compile_features(test_str PRIVATE c_std_23)
|
||||||
add_test(NAME test_str COMMAND test_str)
|
add_test(NAME test_str COMMAND test_str)
|
||||||
|
list(APPEND TEST_TARGETS test_str)
|
||||||
|
|
||||||
# report tests — mocks logger.h so log_info calls are intercepted
|
# report tests — mocks logger.h so log_info calls are intercepted
|
||||||
add_executable(test_report test_report.c)
|
add_executable(test_report test_report.c)
|
||||||
@@ -42,6 +45,7 @@ target_link_libraries(test_report PRIVATE ctdd_report Unity::Unity CMock::CMock)
|
|||||||
target_compile_features(test_report PRIVATE c_std_23)
|
target_compile_features(test_report PRIVATE c_std_23)
|
||||||
cmock_generate_mock(test_report "${CMAKE_SOURCE_DIR}/ctdd/logger.h")
|
cmock_generate_mock(test_report "${CMAKE_SOURCE_DIR}/ctdd/logger.h")
|
||||||
add_test(NAME test_report COMMAND test_report)
|
add_test(NAME test_report COMMAND test_report)
|
||||||
|
list(APPEND TEST_TARGETS test_report)
|
||||||
|
|
||||||
# logger tests — mocks log_write.h so output calls are intercepted
|
# logger tests — mocks log_write.h so output calls are intercepted
|
||||||
add_executable(test_logger test_logger.c)
|
add_executable(test_logger test_logger.c)
|
||||||
@@ -50,3 +54,40 @@ target_link_libraries(test_logger PRIVATE ctdd_logger Unity::Unity CMock::CMock)
|
|||||||
target_compile_features(test_logger PRIVATE c_std_23)
|
target_compile_features(test_logger PRIVATE c_std_23)
|
||||||
cmock_generate_mock(test_logger "${CMAKE_SOURCE_DIR}/ctdd/log_write.h")
|
cmock_generate_mock(test_logger "${CMAKE_SOURCE_DIR}/ctdd/log_write.h")
|
||||||
add_test(NAME test_logger COMMAND test_logger)
|
add_test(NAME test_logger COMMAND test_logger)
|
||||||
|
list(APPEND TEST_TARGETS test_logger)
|
||||||
|
|
||||||
|
# 'check' builds all suites and runs CTest with full Unity output.
|
||||||
|
# USES_TERMINAL keeps ANSI colors alive through Ninja's output buffering.
|
||||||
|
add_custom_target(check
|
||||||
|
COMMAND ${CMAKE_CTEST_COMMAND}
|
||||||
|
--test-dir "${CMAKE_BINARY_DIR}"
|
||||||
|
--output-on-failure
|
||||||
|
--progress
|
||||||
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
|
USES_TERMINAL
|
||||||
|
DEPENDS ${TEST_TARGETS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (ENABLE_COVERAGE)
|
||||||
|
set(COVERAGE_DIR "${CMAKE_BINARY_DIR}/coverage")
|
||||||
|
add_custom_target(coverage
|
||||||
|
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${COVERAGE_DIR}"
|
||||||
|
COMMAND ${GCOVR_EXE}
|
||||||
|
--gcov-executable "${GCOV_EXECUTABLE}"
|
||||||
|
--root "${CMAKE_SOURCE_DIR}"
|
||||||
|
--filter "${CMAKE_SOURCE_DIR}/ctdd/"
|
||||||
|
--exclude "${CMAKE_SOURCE_DIR}/tests/"
|
||||||
|
--exclude ".*Mock.*"
|
||||||
|
--exclude ".*unity.*"
|
||||||
|
--exclude ".*cmock.*"
|
||||||
|
--html-details "${COVERAGE_DIR}/index.html"
|
||||||
|
--txt
|
||||||
|
--print-summary
|
||||||
|
"${CMAKE_BINARY_DIR}"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
|
USES_TERMINAL
|
||||||
|
DEPENDS ${TEST_TARGETS}
|
||||||
|
COMMENT "Coverage report: ${COVERAGE_DIR}/index.html"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|||||||
Reference in New Issue
Block a user