* Add ranges * Initial Hugo setup * Work in progress * Added selection for local or remote site * Updated to 'light' theme * Changed to using Hextra Hugo theme * Changed to using Hextra Hugo theme * Changed to Hextra Hugo theme * Change to Hextra Hugo theme * Updated Hugo setup. * Updated Hugo setup. # Conflicts: # docs/releases/_index.md * Work in progress * Added new fonts Added new documentation * Latest documentation updates * Latest documentation updates # Conflicts: # docs/containers/array.md # docs/containers/array_view.md # docs/containers/array_wrapper.md # docs/containers/bip_buffer_spsc_atomic.md # docs/containers/bitset.md # docs/containers/indirect_vector.md # docs/containers/vector.md # docs/getting-started/compilers.md * Added bloom_filter markdown doc * Added more documentation Updated CSS for light and dark modes * Fixed some menus Added mode documentation files * Updated CSS rules Added badges to home page Added uniqur_ptr + pool tutorial * Fixed formatting on the home page markdown Modified light amd dark code formatting * Updated unique_ptr-with-pool * Added container and shared message tutorials * Updates to documentation * Added const_multimap * Updated source-formatting.md * Added initial raw text files form Web site editor * Innore coverage build directory * Exported raw text documentation files from the web site editor * Hugo updates * Added Hugo intalation and markdown descriptions * More addition to the documentation * Added closure.md and updates to delegate.md * Added format.md * Added documentation for etl::delegate_observable, etl::function, Base64 codec * Added io_port documentation * Added basic_format_spec * Added documentation for string_stream and string utilities. * Added more documentation Updated the documentation CSS * Added documentation for clocks, day, duration * Added more documentation for chrono classes Updated callouts * More chrono documentation * Completed chrono documentation * Maths functions documentation * Completed maths documentation * Completed maths documentation * Completed maths documentation * Completed maths documentation * Added multiple documentation files * Added iterator.md * Added debug_count.md and versions.md * Added debug_count.md and versions.md * Added more documentation * More documentation * Added some design pattern documentation Modified some of the layout files Modified the About documentation * Converted more documentation pages Modified the site CSS * Added more documentation Moced some documentation files to new directories * Added more documentation Tweaks to CSS * Added callback_timer_deferred_locked documentation * Added callback_timer_locked documentation * More documentation updates * More documentation updates * More documentation updates * New documentation files. Harmonised file name format * New documentation files. * Multiple document updates * Multiple document updates * Final conversion of web pages * Updates before PR * Updates before PR * Updates before PR # Conflicts: # docs/blog/_index.md * Final pre PR updates * Updates to message framework documentation * Renamed directory * Fix spelling * Added author and date to blog files Moved documentation files merged from development * Fixed 'Description' typo * Fix typos # Conflicts: # docs/IO/io_port.md # docs/containers/sets/const-multiset.md # docs/containers/sets/const-set.md # docs/maths/correlation.md # docs/maths/gamma.md * Renamed two files to lower case * Minor renaming * Added author and date * Updated callout on bresenham_line.md Added support for showing the ETL version on the documentation first page, by copying the version.txt file as a hugo asset. Updated the Python 'update_release.py' to copy 'version.txt' * Replace space in filename with hyphen. Added more information to hugo-commands.md * Replace space in filename with hyphen. Added more information to hugo-commands.md # Conflicts: # docs/getting-started/view-the-docs-locally/hugo-commands.md * Added a link to pseudo_moving_average.md * Updated title pages for groups * Fixed missing 404 for non-existent pages * Fixed coordinate variable names in the 'Calculating the intersection' example --------- Co-authored-by: Roland Reichwein <Roland.Reichwein@bmw.de> Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com> Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.co.uk>
14 KiB
| title | weight |
|---|---|
| Testing the ETL | 6 |
This document describes how to build and run the ETL test suite locally, inside Dev Containers, and in CI.
Table of Contents
- Prerequisites
- Running Tests Locally (
test/run-tests.sh) - Syntax Checks (
test/run-syntax-checks.sh) - Cross-Architecture Testing (
.devcontainer/run-tests.sh) - Dev Containers for Native Compilers
- CMake Options Reference
- CI Checks (GitHub Actions)
- Appveyor (Windows / MSVC)
- Code Coverage
- Generator Tests (
scripts/generator_test.py)
Prerequisites
- CMake ≥ 3.10
- GCC and/or Clang (any version supported by the project)
- Make or Ninja (build backend)
- Docker (only needed for cross-architecture testing via
.devcontainer/run-tests.sh) - QEMU user-mode (installed automatically inside the cross-arch Docker images)
The project is header-only, so there is no library to compile – the build
step compiles the test binary etl_tests which links against a bundled copy
of UnitTest++.
Running Tests Locally
The main entry point for local testing is test/run-tests.sh. It
iterates over a matrix of compiler / configuration combinations, creates a
temporary build-make directory for each one, runs CMake + Make + CTest,
and reports coloured pass/fail output (also appended to log.txt).
Synopsis
cd test
./run-tests.sh <C++ Standard> [Optimisation] [Threads] [Sanitizer] [Compiler] [Verbose]
| Argument | Values | Default |
|---|---|---|
| C++ Standard | 11, 14, 17, 20, 23, or all |
(required) |
| Optimisation | 0, 1, 2, 3 |
0 |
| Threads | any positive integer | 4 |
| Sanitizer | s (enable) / n (disable) |
n (disabled) |
| Compiler | gcc, clang |
all compilers |
| Verbose | v (enable) / n (disable) |
n (disabled) |
Examples
# Run all C++17 tests with GCC only, optimisation -O0, 8 threads
./run-tests.sh 17 0 8 n gcc
# Run every standard with both compilers, sanitizers enabled, verbose
./run-tests.sh all 0 4 s "" v
What the script does
For every selected C++ standard the script loops over a built-in list of configurations (STL / No STL / Force C++03 / Non-virtual messages / …) for each selected compiler. For every combination it:
- Creates a fresh
build-makedirectory inside the configuration's source subdirectory. - Invokes
cmakewith the appropriate-Dflags (see CMake Options Reference). - Builds via
cmake --build .(parallel level controlled byCMAKE_BUILD_PARALLEL_LEVEL). - Runs
ctest -V. - Reports success or failure and removes the build directory.
The script exits immediately on the first compilation or test failure.
Test configurations exercised
| Compiler | Configuration |
|---|---|
| GCC | STL |
| GCC | STL – Non-virtual messages |
| GCC | STL – Force C++03 |
| GCC | No STL |
| GCC | No STL – Force C++03 |
| GCC | No STL – Builtin mem functions |
| Clang | STL |
| Clang | STL – Force C++03 |
| Clang | No STL |
| Clang | No STL – Force C++03 |
| Clang | No STL – Builtin mem functions |
| GCC / Clang | Initializer list test |
| GCC / Clang | Error macros – log_errors, exceptions, log_errors_and_exceptions, assert_function |
Syntax Checks
The script test/run-syntax-checks.sh performs compilation-only syntax
checks across multiple C++ standards and configurations. Unlike
run-tests.sh, it does not run the test binary – it only verifies that
the code compiles successfully. This is useful for quickly validating that
header changes do not introduce compilation errors across the supported
standard/configuration matrix.
Synopsis
cd test
./run-syntax-checks.sh <C++ Standard> [Threads] [Compiler]
| Argument | Values | Default |
|---|---|---|
| C++ Standard | 03, 11, 14, 17, 20, 23, or a (all) |
(required) |
| Threads | any positive integer | 4 |
| Compiler | gcc, clang |
all compilers |
Examples
# Check C++17 syntax with GCC only, using 8 threads
./run-syntax-checks.sh 17 8 gcc
# Check all standards with both compilers
./run-syntax-checks.sh a
What the script does
The script operates from the test/syntax_check directory and iterates over
the selected C++ standard(s). For each standard and compiler combination it:
- Creates fresh build directories (
bgcc/bclang). - Invokes
cmakewith the appropriate-Dflags for the configuration. - Builds via
cmake --build. - Reports compilation success or failure (logged to
log.txt).
The script exits immediately on the first compilation failure.
Configurations checked per standard
For each C++ standard the following configurations are compiled:
| Compiler | Configuration |
|---|---|
| GCC | STL |
| GCC | No STL |
| GCC | STL – Built-in traits |
| GCC | No STL – Built-in traits |
| Clang | STL |
| Clang | No STL |
| Clang | STL – Built-in traits |
| Clang | No STL – Built-in traits |
Cross-Architecture Testing
.devcontainer/run-tests.sh builds and runs the test suite for
non-x86_64 architectures using Docker and QEMU user-mode emulation. It is
designed to be run from the project root.
Supported architectures
| Argument | Target | Endianness | QEMU binary |
|---|---|---|---|
armhf |
ARM hard-float (32-bit) | Little | qemu-arm-static |
i386 |
x86 32-bit | Little | qemu-i386-static |
powerpc |
PowerPC 32-bit | Big | qemu-ppc |
riscv64 |
RISC-V 64-bit | Little | qemu-riscv64-static |
s390x |
IBM Z (64-bit) | Big | qemu-s390x-static |
Synopsis
# From the project root
.devcontainer/run-tests.sh <architecture>
How it works
The script has two phases controlled by a second (internal) argument:
-
Outside the container (no second argument):
- Builds a Docker image from
.devcontainer/<arch>/Dockerfile. - Starts a container, bind-mounting the project at
/workspaces/etl. - Re-invokes itself inside the container with the
inside_containerflag.
- Builds a Docker image from
-
Inside the container (
inside_container):- Creates
build-<arch>and runs CMake with the appropriate cross- compilation toolchain file (.devcontainer/<arch>/toolchain-<arch>.cmake). - Builds with
cmake --build .using all available cores. - Runs the test suite via
ctest --output-on-failure.
- Creates
The toolchain files set CMAKE_CROSSCOMPILING_EMULATOR so that CTest can
run the binary transparently through QEMU.
Example
# Build & run the armhf test suite
.devcontainer/run-tests.sh armhf
The cross-arch containers build with the following fixed settings:
- C++23, No STL, sanitizer off, optimisation -O0.
Dev Containers for Native Compilers
The .devcontainer/ directory also provides Dev Container definitions for a
wide range of native (x86_64) compiler versions. These are intended for
use with VS Code Dev Containers or GitHub Codespaces.
| Directory | Compiler |
|---|---|
gcc09 – gcc15 |
GCC 9 through 15 |
clang7 – clang21 |
Clang 7 through 21 |
Each subdirectory contains a devcontainer.json that references the shared
Dockerfile (.devcontainer/Dockerfile) and passes the appropriate base
Docker image via the BASE_IMAGE_NAME build argument (e.g. gcc:15).
The default Dev Container (.devcontainer/devcontainer.json) uses the
Microsoft C++ dev-container base image.
To use one of these containers:
- Open the repository in VS Code.
- Ctrl+Shift+P → Dev Containers: Reopen in Container and select the desired configuration (e.g. Gcc 15).
- Use
test/run-tests.shinside the container as described above.
CMake Options Reference
When invoking CMake for the test suite (source directory is test/), the
following -D options control the build:
| Option | Type | Description |
|---|---|---|
BUILD_TESTS |
BOOL |
Must be ON to compile the test binary. |
NO_STL |
BOOL |
Build without the C++ Standard Library. |
ETL_CXX_STANDARD |
STRING |
C++ standard: 11, 14, 17, 20, 23. |
ETL_OPTIMISATION |
STRING |
Compiler optimisation flag, e.g. -O0. |
ETL_ENABLE_SANITIZER |
BOOL |
Enable address / undefined-behaviour sanitizers. |
ETL_USE_TYPE_TRAITS_BUILTINS |
BOOL |
Use compiler built-in type traits. |
ETL_USER_DEFINED_TYPE_TRAITS |
BOOL |
Use user-defined type traits. |
ETL_FORCE_TEST_CPP03_IMPLEMENTATION |
BOOL |
Force the C++03 code paths even on newer standards. |
ETL_MESSAGES_ARE_NOT_VIRTUAL |
BOOL |
Use non-virtual message types. |
ETL_USE_BUILTIN_MEM_FUNCTIONS |
BOOL |
Use built-in memory functions in No-STL mode. |
CMAKE_TOOLCHAIN_FILE |
PATH |
Toolchain file for cross-compilation. |
Minimal manual build example
cd test
mkdir build && cd build
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_CXX_STANDARD=20 ..
cmake --build . -j$(nproc)
ctest -V
CI Checks (GitHub Actions)
Every push or pull request to master, development, or pull-request/*
branches triggers a comprehensive set of GitHub Actions workflows defined in
.github/workflows/.
Workflow matrix
| Workflow file | Compiler | Standard | Notes |
|---|---|---|---|
gcc-c++11.yml |
GCC | C++11 | STL, No STL, Force C++03 |
gcc-c++14.yml |
GCC | C++14 | STL, No STL, Force C++03 |
gcc-c++17.yml |
GCC | C++17 | STL, No STL, Force C++03 |
gcc-c++20.yml |
GCC | C++20 | STL, No STL, Force C++03 |
gcc-c++23.yml |
GCC | C++23 | STL, No STL, Force C++03 |
clang-c++11.yml |
Clang | C++11 | STL, No STL, Force C++03 |
clang-c++14.yml |
Clang | C++14 | STL, No STL, Force C++03 |
clang-c++17.yml |
Clang | C++17 | STL, No STL, Force C++03 |
clang-c++20.yml |
Clang | C++20 | STL, No STL, Force C++03 |
clang-c++23.yml |
Clang | C++23 | STL, No STL, Force C++03 |
gcc-syntax-checks.yml |
GCC | C++03 – C++23 | Compilation-only syntax checks (no tests run) |
clang-syntax-checks.yml |
Clang | C++03 – C++23 | Compilation-only syntax checks (no tests run) |
msvc.yml |
MSVC 2022 | C++17 | Windows, STL & No STL |
gcc-c++23-armhf.yml |
GCC cross | C++23 | armhf via QEMU |
gcc-c++23-i386.yml |
GCC cross | C++23 | i386 via QEMU |
gcc-c++23-powerpc.yml |
GCC cross | C++23 | powerpc via QEMU |
gcc-c++23-riscv64.yml |
GCC cross | C++23 | RISC-V 64 via QEMU |
gcc-c++23-s390x.yml |
GCC cross | C++23 | s390x via QEMU |
coverage.yml |
GCC | — | Generates lcov coverage report, deploys to GitHub Pages |
generator.yml |
— | — | Runs the code generator |
platformio-update.yml |
— | — | PlatformIO registry update |
Typical CI job structure
Each compiler/standard workflow follows the same pattern:
- Checkout –
actions/checkout@v4. - Build – set
CC/CXX, callcmakewith the appropriate-Dflags, thenmake -j. - Run tests – execute
./test/etl_tests -v(orctest -Vfor cross- arch jobs).
The cross-architecture CI jobs additionally install a cross-compiler
toolchain and QEMU inside a debian:trixie container, use the matching
toolchain file from .devcontainer/<arch>/, and run tests via CTest (which
delegates to QEMU through CMAKE_CROSSCOMPILING_EMULATOR).
Branches tested
masterdevelopmentpull-request/*
All workflows run on both push and pull_request events (types: opened,
synchronize, reopened).
Appveyor (Windows / MSVC)
The appveyor.yml at the repository root provides additional Windows CI
using Visual Studio 2022. It builds the master branch only.
Configurations tested:
- Debug MSVC C++14
- Debug MSVC C++14 – No STL
- Debug MSVC C++17
- Debug MSVC C++17 – No STL
- Debug MSVC C++20
- Debug MSVC C++20 – No STL
The build uses the VS 2022 solution file at test/vs2022/etl.vcxproj.
Code Coverage
The coverage.yml GitHub Actions workflow generates an lcov coverage
report:
- Runs
test/run-coverage.shwhich builds and tests with GCC coverage flags. - Uploads the HTML report as a build artifact (retained for 30 days).
- On pushes to
master, deploys the report to GitHub Pages.
To generate coverage locally:
cd test
./run-coverage.sh
# Open test/build-coverage/coverage/index.html
Generator Tests
The script scripts/generator_test.py verifies that the code generators
in include/etl/generators/ produce output matching the checked-in header
files in include/etl/private/.
ETL uses Cog to generate certain
repetitive header files (e.g. delegate.h, message_packet.h). The
generator templates live in include/etl/generators/*_generator.h and the
generated output is committed to include/etl/private/*.h. This test
ensures the two stay in sync.
Prerequisites
- Python 3
- cogapp – install via
pip install cogapp
Synopsis
python3 scripts/generator_test.py
What the script does
- Iterates over every
*_generator.hfile ininclude/etl/generators/. - Runs Cog on each generator, outputting to
build/generator_tmp/. - Compares each generated file against the corresponding file in
include/etl/private/. - Reports success if all files match, or failure if any differ.
The script exits with code 0 on success and 1 on failure.
CI integration
The generator.yml GitHub Actions workflow runs this script automatically
on pushes and pull requests to verify generator consistency.