Extensions for testing (#1380)

* Extensions for testing

Generalize run-tests.sh

Test all C++ versions at once

Fix combination of big endian and -Wsign-conversion

Failed on s390x (as reference for big endian)

Add github workflow for s390x

Add armhf container files

Devcontainers for i386 and riscv

Add github workflows for armhf, i386 and riscv64

Add run-tests.sh for foreign architectures

Document testing in doc/testing.md

Adjustments from clang-format run

Fix .devcontainer/s390x/Dockerfile for linebreak syntax

Fix exit code of run-test.sh

Previously, "exit $?" was used, actually the return value of
FailedCompilation and FailedTest which are always 0.

Now just using 1.

In run-tests.sh at ctest, use -V for printing number of tests unconditionally

While ctest suppresses individual test list by default, it didn't even
print the number of tests anymore, as run_tests.sh does because
it suppresses it output completely.

Now, by default print number of tests, and in verbose mode, print test list
in addition.

* Support powerpc as foreign architecture

* Add SFINAE constraints to etl::begin/end and reverse iterator free functions

The unconstrained etl::begin(), etl::end(), etl::cbegin(), etl::cend(),
etl::rbegin(), etl::rend(), etl::crbegin(), and etl::crend() templates
in the no-STL code path were matching iterator types during ADL, causing
a hard error with GCC 15's std::ranges::begin. When std::ranges performed
ADL on an etl::*::iterator, it found etl::begin() as a candidate; since
the iterator type has a nested iterator typedef, the return type TContainer::iterator
was valid, but calling .begin() on the iterator failed.

Fix: add etl::void_t<decltype(...)> SFINAE guards to each template,
ensuring they only participate in overload resolution when TContainer
actually has the corresponding member function (.begin(), .end(), etc.).

* - Fix red unit tests on 32 bits big-endian platform.

* Document powerpc architecture for testing

* Use Dockerfiles in cross testing github workflows

Synchronizes environment setup for github workflows to what is
defined in the development Dockerfiles. So they don't need to
be maintained separately.

---------

Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
Co-authored-by: Sergei Shirokov <sergej.shirokov@gmail.com>
Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
This commit is contained in:
Roland Reichwein 2026-04-15 10:47:52 +02:00 committed by GitHub
parent 17799452d2
commit 866c8a315e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 1582 additions and 127 deletions

View File

@ -0,0 +1,54 @@
# armhf Test Environment for ETL
# Uses QEMU user-mode emulation to run armhf binaries on x64 host
FROM debian:trixie
# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Install QEMU user-mode emulation and armhf cross-compilation tools
RUN dpkg --add-architecture armhf && \
apt-get update && apt-get install -y --no-install-recommends \
qemu-user-static \
qemu-user \
binfmt-support \
gcc-arm-linux-gnueabihf \
g++-arm-linux-gnueabihf \
cmake \
make \
ninja-build \
git \
wget \
file \
libc6:armhf \
libstdc++6:armhf \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with stable UID/GID
ARG USERNAME=devuser
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Set working directory
WORKDIR /workspaces/etl
# Verify QEMU and cross-compilation setup
RUN echo "=== Host Architecture ===" && \
uname -m && \
echo "" && \
echo "=== armhf Cross Compiler ===" && \
arm-linux-gnueabihf-gcc --version && \
echo "" && \
echo "=== QEMU arm ===" && \
qemu-arm-static --version | head -n1
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces
# Switch to non-root user
USER ${USERNAME}
# Default command
CMD ["/bin/bash"]

View File

@ -0,0 +1,29 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
{
"name": "armhf (Debian)",
"build": {
"dockerfile": "./Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
],
"settings": {
"cmake.sourceDirectory": "${workspaceFolder}/test",
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/armhf/toolchain-armhf.cmake",
"-DBUILD_TESTS=ON",
"-DNO_STL=OFF",
"-DETL_CXX_STANDARD=23"
],
"cmake.buildDirectory": "${workspaceFolder}/build-armhf",
"cmake.generator": "Ninja"
}
}
},
"remoteUser": "root"
}

View File

@ -0,0 +1,21 @@
# CMake toolchain file for armhf cross-compilation
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# Specify the cross compiler
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_AR arm-linux-gnueabihf-ar)
set(CMAKE_RANLIB arm-linux-gnueabihf-ranlib)
set(CMAKE_STRIP arm-linux-gnueabihf-strip)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Set QEMU for running tests
set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-arm-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries")

View File

@ -0,0 +1,54 @@
# i386 Test Environment for ETL
# Uses QEMU user-mode emulation to run i386 binaries on x64 host
FROM debian:trixie
# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Install QEMU user-mode emulation and i386 cross-compilation tools
RUN dpkg --add-architecture i386 && \
apt-get update && apt-get install -y --no-install-recommends \
qemu-user-static \
qemu-user \
binfmt-support \
gcc-i686-linux-gnu \
g++-i686-linux-gnu \
cmake \
make \
ninja-build \
git \
wget \
file \
libc6:i386 \
libstdc++6:i386 \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with stable UID/GID
ARG USERNAME=devuser
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Set working directory
WORKDIR /workspaces/etl
# Verify QEMU and cross-compilation setup
RUN echo "=== Host Architecture ===" && \
uname -m && \
echo "" && \
echo "=== i386 Cross Compiler ===" && \
i686-linux-gnu-gcc --version && \
echo "" && \
echo "=== QEMU i386 ===" && \
qemu-i386-static --version | head -n1
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces
# Switch to non-root user
USER ${USERNAME}
# Default command
CMD ["/bin/bash"]

View File

@ -0,0 +1,29 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
{
"name": "i386 (Debian)",
"build": {
"dockerfile": "./Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
],
"settings": {
"cmake.sourceDirectory": "${workspaceFolder}/test",
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/i386/toolchain-i386.cmake",
"-DBUILD_TESTS=ON",
"-DNO_STL=OFF",
"-DETL_CXX_STANDARD=23"
],
"cmake.buildDirectory": "${workspaceFolder}/build-i386",
"cmake.generator": "Ninja"
}
}
},
"remoteUser": "root"
}

View File

@ -0,0 +1,21 @@
# CMake toolchain file for i386 cross-compilation
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR i386)
# Specify the cross compiler
set(CMAKE_C_COMPILER i686-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER i686-linux-gnu-g++)
set(CMAKE_AR i686-linux-gnu-ar)
set(CMAKE_RANLIB i686-linux-gnu-ranlib)
set(CMAKE_STRIP i686-linux-gnu-strip)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Set QEMU for running tests
set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-i386-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries")

View File

@ -0,0 +1,71 @@
# powerpc Test Environment for ETL
# Uses QEMU user-mode emulation to run powerpc binaries on x64 host
FROM debian:sid-20260406
# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Install QEMU user-mode emulation and powerpc cross-compilation tools
RUN dpkg --add-architecture powerpc && \
apt-get update && apt-get install -y --no-install-recommends \
binfmt-support \
gpg \
ca-certificates \
cmake \
make \
ninja-build \
git \
wget \
file \
debian-ports-archive-keyring \
&& rm -rf /var/lib/apt/lists/*
RUN cat <<EOF > /etc/apt/sources.list.d/powerpc.sources
Types: deb
URIs: http://snapshot.debian.org/archive/debian-ports/20260406T000000Z
Suites: sid
Components: main
Architectures: powerpc
Signed-By: /usr/share/keyrings/debian-ports-archive-keyring.gpg
EOF
RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf.d/99no-check-valid
RUN apt-get update && apt-get install -y --no-install-recommends \
qemu-user-static \
qemu-user \
gcc-powerpc-linux-gnu \
g++-powerpc-linux-gnu \
libc6:powerpc \
libstdc++6:powerpc \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with stable UID/GID
ARG USERNAME=devuser
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Set working directory
WORKDIR /workspaces/etl
# Verify QEMU and cross-compilation setup
RUN echo "=== Host Architecture ===" && \
uname -m && \
echo "" && \
echo "=== powerpc Cross Compiler ===" && \
powerpc-linux-gnu-gcc --version && \
echo "" && \
echo "=== QEMU powerpc ===" && \
qemu-ppc-static --version | head -n1
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces
# Switch to non-root user
USER ${USERNAME}
# Default command
CMD ["/bin/bash"]

View File

@ -0,0 +1,29 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
{
"name": "powerpc (Debian)",
"build": {
"dockerfile": "./Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
],
"settings": {
"cmake.sourceDirectory": "${workspaceFolder}/test",
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/powerpc/toolchain-powerpc.cmake",
"-DBUILD_TESTS=ON",
"-DNO_STL=ON",
"-DETL_CXX_STANDARD=23"
],
"cmake.buildDirectory": "${workspaceFolder}/build-powerpc",
"cmake.generator": "Ninja"
}
}
},
"remoteUser": "root"
}

View File

@ -0,0 +1,21 @@
# CMake toolchain file for powerpc cross-compilation
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR powerpc)
# Specify the cross compiler
set(CMAKE_C_COMPILER powerpc-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER powerpc-linux-gnu-g++)
set(CMAKE_AR powerpc-linux-gnu-ar)
set(CMAKE_RANLIB powerpc-linux-gnu-ranlib)
set(CMAKE_STRIP powerpc-linux-gnu-strip)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Set QEMU for running tests
set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-ppc CACHE FILEPATH "Path to the emulator for cross-compiled binaries")

View File

@ -0,0 +1,54 @@
# riscv64 Test Environment for ETL
# Uses QEMU user-mode emulation to run riscv64 binaries on x64 host
FROM debian:trixie
# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Install QEMU user-mode emulation and riscv64 cross-compilation tools
RUN dpkg --add-architecture riscv64 && \
apt-get update && apt-get install -y --no-install-recommends \
qemu-user-static \
qemu-user \
binfmt-support \
gcc-riscv64-linux-gnu \
g++-riscv64-linux-gnu \
cmake \
make \
ninja-build \
git \
wget \
file \
libc6:riscv64 \
libstdc++6:riscv64 \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with stable UID/GID
ARG USERNAME=devuser
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Set working directory
WORKDIR /workspaces/etl
# Verify QEMU and cross-compilation setup
RUN echo "=== Host Architecture ===" && \
uname -m && \
echo "" && \
echo "=== riscv64 Cross Compiler ===" && \
riscv64-linux-gnu-gcc --version && \
echo "" && \
echo "=== QEMU riscv64 ===" && \
qemu-riscv64-static --version | head -n1
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces
# Switch to non-root user
USER ${USERNAME}
# Default command
CMD ["/bin/bash"]

View File

@ -0,0 +1,29 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
{
"name": "riscv64 (Debian)",
"build": {
"dockerfile": "./Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
],
"settings": {
"cmake.sourceDirectory": "${workspaceFolder}/test",
"cmake.configureArgs": [
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/riscv64/toolchain-riscv64.cmake",
"-DBUILD_TESTS=ON",
"-DNO_STL=OFF",
"-DETL_CXX_STANDARD=23"
],
"cmake.buildDirectory": "${workspaceFolder}/build-riscv64",
"cmake.generator": "Ninja"
}
}
},
"remoteUser": "root"
}

View File

@ -0,0 +1,20 @@
# CMake toolchain file for riscv64 cross-compilation
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR riscv64)
# Specify the cross compiler
set(CMAKE_C_COMPILER riscv64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER riscv64-linux-gnu-g++)
set(CMAKE_AR riscv64-linux-gnu-ar)
set(CMAKE_RANLIB riscv64-linux-gnu-ranlib)
set(CMAKE_STRIP riscv64-linux-gnu-strip)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Set QEMU for running tests
set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-riscv64-static CACHE FILEPATH "Path to the emulator for cross-compiled binaries")

56
.devcontainer/run-tests.sh Executable file
View File

@ -0,0 +1,56 @@
#!/bin/bash
#
# Run tests inside the separately created docker container for different hardware architecture
#
# Strategy:
# * Create docker image
# * Enter image
# * Cross build tests
# * Run tests via QEMU
#
set -e
usage()
{
echo "Usage: run-tests.sh <architecture>"
echo "Architecture: armhf|i386|powerpc|riscv64|s390x"
echo "(run from project root)"
}
ARCHLIST="armhf i386 powerpc riscv64 s390x"
if [[ " $ARCHLIST " =~ " $1 " ]] ; then
ARCH=$1
else
echo "Unsupported architecture: $1"
usage
exit 1
fi
if [ "$2" = "" ] ; then
echo "Creating docker image..."
docker build -t $ARCH .devcontainer/$ARCH
echo "Entering container..."
docker run -it --rm -v "$PWD":/workspaces/etl -w /workspaces/etl $ARCH /bin/bash .devcontainer/run-tests.sh $ARCH inside_container
elif [ "$2" = "inside_container" ] ; then
echo "Cross building tests..."
mkdir -p build-$ARCH
cd build-$ARCH
cmake -DCMAKE_TOOLCHAIN_FILE=../.devcontainer/$ARCH/toolchain-$ARCH.cmake \
-DBUILD_TESTS=ON -DNO_STL=ON -DETL_CXX_STANDARD=23 \
-DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=-O0 -DETL_ENABLE_SANITIZER=Off -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF \
../test
export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
cmake --build .
echo "Running tests via CTest (using QEMU emulator from toolchain)..."
ctest -V --output-on-failure
echo "Tests successful."
else
echo "Invalid second argument: $2"
usage
exit 1
fi

View File

@ -7,7 +7,7 @@ ENV DEBIAN_FRONTEND=noninteractive
# Install QEMU user-mode emulation and s390x cross-compilation tools
RUN dpkg --add-architecture s390x && \
apt-get update && apt-get install -y --no-install-recommends\
apt-get update && apt-get install -y --no-install-recommends \
qemu-user-static \
qemu-user \
binfmt-support \
@ -23,6 +23,14 @@ RUN dpkg --add-architecture s390x && \
libstdc++6:s390x \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user with stable UID/GID
ARG USERNAME=devuser
ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --gid ${USER_GID} ${USERNAME} && \
useradd --uid ${USER_UID} --gid ${USER_GID} --shell /bin/bash --create-home ${USERNAME}
# Set working directory
WORKDIR /workspaces/etl
@ -36,5 +44,11 @@ RUN echo "=== Host Architecture ===" && \
echo "=== QEMU s390x ===" && \
qemu-s390x-static --version | head -n1
# Ensure workspace directory ownership for non-root user
RUN mkdir -p /workspaces/etl && chown -R ${USERNAME}:${USERNAME} /workspaces
# Switch to non-root user
USER ${USERNAME}
# Default command
CMD ["/bin/bash"]

View File

@ -18,7 +18,7 @@
"-DCMAKE_TOOLCHAIN_FILE=${workspaceFolder}/.devcontainer/s390x/toolchain-s390x.cmake",
"-DBUILD_TESTS=ON",
"-DNO_STL=OFF",
"-DETL_CXX_STANDARD=17"
"-DETL_CXX_STANDARD=23"
],
"cmake.buildDirectory": "${workspaceFolder}/build-s390x",
"cmake.generator": "Ninja"

View File

@ -30,7 +30,7 @@ jobs:
export CC=clang-17
export CXX=clang++-17
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./
clang-17 --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -59,7 +59,7 @@ jobs:
export CC=clang-17
export CXX=clang++-17
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./
clang-17 --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -88,7 +88,7 @@ jobs:
export CC=clang-17
export CXX=clang++-17
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./
clang-17 --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -110,7 +110,7 @@ jobs:
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -132,7 +132,7 @@ jobs:
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -154,7 +154,7 @@ jobs:
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
cmake -D BUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -176,7 +176,7 @@ jobs:
export CC=clang
export CXX=clang++
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
cmake -D BUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./
clang --version
make -j $(getconf _NPROCESSORS_ONLN)

29
.github/workflows/gcc-c++23-armhf.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: gcc-c++23-armhf
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp23-linux-no-stl-armhf:
name: GCC C++23 Linux - No STL - armhf
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-armhf -f .devcontainer/armhf/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-armhf bash -c "\
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
-DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/armhf/toolchain-armhf.cmake \
-DEXTRA_TESTING_FLAGS=-v \
./ && \
cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \
ctest -V"

29
.github/workflows/gcc-c++23-i386.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: gcc-c++23-i386
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp23-linux-no-stl-i386:
name: GCC C++23 Linux - No STL - i386
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-i386 -f .devcontainer/i386/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-i386 bash -c "\
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
-DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/i386/toolchain-i386.cmake \
-DEXTRA_TESTING_FLAGS=-v \
./ && \
cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \
ctest -V"

29
.github/workflows/gcc-c++23-powerpc.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: gcc-c++23-powerpc
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp23-linux-no-stl-powerpc:
name: GCC C++23 Linux - No STL - powerpc
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-powerpc -f .devcontainer/powerpc/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-powerpc bash -c "\
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
-DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/powerpc/toolchain-powerpc.cmake \
-DEXTRA_TESTING_FLAGS=-v \
./ && \
cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \
ctest -V"

29
.github/workflows/gcc-c++23-riscv64.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: gcc-c++23-riscv64
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp23-linux-no-stl-riscv64:
name: GCC C++23 Linux - No STL - riscv64
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-riscv64 -f .devcontainer/riscv64/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-riscv64 bash -c "\
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
-DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/riscv64/toolchain-riscv64.cmake \
-DEXTRA_TESTING_FLAGS=-v \
./ && \
cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \
ctest -V"

29
.github/workflows/gcc-c++23-s390x.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: gcc-c++23-s390x
on:
push:
branches: [ master, development, pull-request/* ]
pull_request:
branches: [ master, development, pull-request/* ]
types: [opened, synchronize, reopened]
jobs:
build-gcc-cpp23-linux-no-stl-s390x:
name: GCC C++23 Linux - No STL - s390x
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t etl-s390x -f .devcontainer/s390x/Dockerfile .
- name: Build and run tests
run: |
docker run --rm --user root -v ${{ github.workspace }}:/workspaces/etl etl-s390x bash -c "\
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF \
-DETL_CXX_STANDARD=23 -DCMAKE_TOOLCHAIN_FILE=.devcontainer/s390x/toolchain-s390x.cmake \
-DEXTRA_TESTING_FLAGS=-v \
./ && \
cmake --build . -- -j \$(getconf _NPROCESSORS_ONLN) && \
ctest -V"

View File

@ -23,7 +23,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
export CC=gcc
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -45,7 +45,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
export CC=gcc
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=OFF -DETL_CXX_STANDARD=23 ./
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=23 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -67,7 +67,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
export CC=gcc
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
cmake -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)
@ -89,7 +89,7 @@ jobs:
export ASAN_OPTIONS=alloc_dealloc_mismatch=0,detect_leaks=0
export CC=gcc
export CXX=g++
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03=ON -DETL_CXX_STANDARD=23 ./
cmake -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=23 ./
gcc --version
make -j $(getconf _NPROCESSORS_ONLN)

190
docs/generators.md Normal file
View File

@ -0,0 +1,190 @@
# Code Generation for Pre-C++11 Support
ETL supports C++03 (also referred to as C++98) environments where variadic
templates, `constexpr`, and other modern features are unavailable. To
provide equivalent functionality, certain headers are **generated** using
[Cog](https://nedbatchelder.com/code/cog/), a Python-based code generation
tool that embeds Python snippets inside source files.
This document explains how the code generation system works and how to
regenerate the headers if you modify a generator template.
---
## Overview
| Directory | Contents |
|---|---|
| `include/etl/generators/` | Generator templates (`*_generator.h`) and batch scripts |
| `include/etl/private/` | Generated output (`*_cpp03.h`) committed to the repository |
| `scripts/generator_test.py` | CI script that verifies generators match committed files |
The generator templates contain embedded Python code (delimited by `[[[cog`
and `]]]`) that produces the repetitive C++03 boilerplate. Cog processes
these templates and writes the expanded output to `include/etl/private/`.
---
## Generated Headers
The following C++03 compatibility headers are generated:
| Generator | Output | Purpose |
|---|---|---|
| `fsm_fwd_decl_cpp03_generator.h` | `fsm_fwd_decl_cpp03.h` | FSM forward declarations |
| `fsm_friend_decl_cpp03_generator.h` | `fsm_friend_decl_cpp03.h` | FSM friend declarations |
| `fsm_cpp03_generator.h` | `fsm_cpp03.h` | Finite state machine implementation |
| `message_router_cpp03_generator.h` | `message_router_cpp03.h` | Message router |
| `message_packet_cpp03_generator.h` | `message_packet_cpp03.h` | Message packet |
| `largest_type_cpp03_generator.h` | `largest_type_cpp03.h` | Largest type metafunction |
| `largest_alignment_cpp03_generator.h` | `largest_alignment_cpp03.h` | Largest alignment metafunction |
| `largest_cpp03_generator.h` | `largest_cpp03.h` | Largest type/size utilities |
| `smallest_cpp03_generator.h` | `smallest_cpp03.h` | Smallest type/size utilities |
| `type_traits_cpp03_generator.h` | `type_traits_cpp03.h` | Type traits (`is_one_of`, etc.) |
| `type_lookup_cpp03_generator.h` | `type_lookup_cpp03.h` | Type lookup metafunction |
| `type_select_cpp03_generator.h` | `type_select_cpp03.h` | Type selection metafunction |
| `variant_pool_cpp03_generator.h` | `variant_pool_cpp03.h` | Variant pool |
---
## Generator Parameters
Cog variables control how many template parameter overloads are generated:
| Variable | Default | Used by |
|---|---|---|
| `Handlers` | 16 | FSM and message router generators |
| `NTypes` | 16 | Type utility generators (largest, smallest, lookup, select, variant pool) |
| `IsOneOf` | 16 | Type traits generator (`is_one_of`) |
These defaults produce overloads supporting up to 16 types or handlers,
which is sufficient for most embedded applications while keeping compile
times reasonable.
---
## Prerequisites
* **Python 3**
* **cogapp** install via:
```bash
pip install cogapp
```
---
## Regenerating Headers
### Using the batch scripts (Windows)
Each generator has a corresponding `.bat` file in `include/etl/generators/`:
```bat
cd include/etl/generators
generate.bat # Regenerate all headers
generate_fsm.bat # Regenerate FSM headers only
generate_smallest.bat # Regenerate smallest_cpp03.h only
# etc.
```
### Manual invocation
Run Cog directly from the `include/etl/generators/` directory:
```bash
cd include/etl/generators
# Example: regenerate smallest_cpp03.h
python3 -m cogapp -d -e -o../private/smallest_cpp03.h -DNTypes=16 smallest_cpp03_generator.h
# Example: regenerate fsm_cpp03.h
python3 -m cogapp -d -e -o../private/fsm_cpp03.h -DHandlers=16 fsm_cpp03_generator.h
```
Cog options used:
| Option | Meaning |
|---|---|
| `-d` | Delete the generator markers from output |
| `-e` | Warn if the input file has no generator markers |
| `-o<file>` | Write output to the specified file |
| `-D<var>=<value>` | Define a Cog variable |
### Regenerating all headers
The `generate.bat` script regenerates every header:
```bash
cd include/etl/generators
./generate.bat # Windows
# or run the commands manually on Linux/macOS
```
On Linux/macOS you can run the commands from `generate.bat` directly in
your shell (they are standard `python3 -m cogapp` invocations).
---
## Verifying Generators
After modifying a generator template, verify the output matches the
committed file:
```bash
python3 scripts/generator_test.py
```
This script:
1. Runs Cog on every `*_generator.h` file.
2. Compares each output against the corresponding file in
`include/etl/private/`.
3. Reports success or failure.
The `generator.yml` GitHub Actions workflow runs this automatically on
every push and pull request.
---
## How Generators Work
A generator template contains standard C++ code interspersed with Cog
directives. For example, from `smallest_cpp03_generator.h`:
```cpp
/*[[[cog
import cog
cog.outl("template <typename T1, ")
for n in range(2, int(NTypes)):
cog.out("typename T%s = void, " % n)
cog.outl("typename T%s = void>" % int(NTypes))
]]]*/
// Generated code appears here after running Cog
/*[[[end]]]*/
```
When Cog processes this file with `-DNTypes=16`, the Python code executes
and outputs the expanded template parameter list supporting 16 types.
---
## Adding a New Generator
1. Create `include/etl/generators/<name>_cpp03_generator.h` with Cog
directives.
2. Add a corresponding entry to `generate.bat`.
3. Run `generate.bat` (or the equivalent Cog command) to produce
`include/etl/private/<name>_cpp03.h`.
4. Commit both the generator and the generated output.
5. Verify with `python3 scripts/generator_test.py`.
---
## Troubleshooting
| Problem | Solution |
|---|---|
| `ModuleNotFoundError: No module named 'cogapp'` | Install Cog: `pip install cogapp` |
| Generator output differs from committed file | Regenerate and commit the updated output |
| Need more than 16 types/handlers | Change `-DNTypes=` or `-DHandlers=` and regenerate |

412
docs/testing.md Normal file
View File

@ -0,0 +1,412 @@
# Testing ETL
This document describes how to build and run the ETL test suite locally,
inside Dev Containers, and in CI.
## Table of Contents
1. [Prerequisites](#prerequisites)
2. [Running Tests Locally (`test/run-tests.sh`)](#running-tests-locally)
3. [Syntax Checks (`test/run-syntax-checks.sh`)](#syntax-checks)
4. [Cross-Architecture Testing (`.devcontainer/run-tests.sh`)](#cross-architecture-testing)
5. [Dev Containers for Native Compilers](#dev-containers-for-native-compilers)
6. [CMake Options Reference](#cmake-options-reference)
7. [CI Checks (GitHub Actions)](#ci-checks-github-actions)
8. [Appveyor (Windows / MSVC)](#appveyor-windows--msvc)
9. [Code Coverage](#code-coverage)
10. [Generator Tests (`scripts/generator_test.py`)](#generator-tests)
---
## 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
```bash
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
```bash
# 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:
1. Creates a fresh `build-make` directory inside the configuration's source
subdirectory.
2. Invokes `cmake` with the appropriate `-D` flags (see
[CMake Options Reference](#cmake-options-reference)).
3. Builds via `cmake --build .` (parallel level controlled by
`CMAKE_BUILD_PARALLEL_LEVEL`).
4. Runs `ctest -V`.
5. 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
```bash
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
```bash
# 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:
1. Creates fresh build directories (`bgcc` / `bclang`).
2. Invokes `cmake` with the appropriate `-D` flags for the configuration.
3. Builds via `cmake --build`.
4. 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
```bash
# From the project root
.devcontainer/run-tests.sh <architecture>
```
### How it works
The script has two phases controlled by a second (internal) argument:
1. **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_container`
flag.
2. **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`.
The toolchain files set `CMAKE_CROSSCOMPILING_EMULATOR` so that CTest can
run the binary transparently through QEMU.
### Example
```bash
# 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:
1. Open the repository in VS Code.
2. **Ctrl+Shift+P → Dev Containers: Reopen in Container** and select the
desired configuration (e.g. *Gcc 15*).
3. Use `test/run-tests.sh` inside 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
```bash
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:
1. **Checkout** `actions/checkout@v4`.
2. **Build** set `CC`/`CXX`, call `cmake` with the appropriate `-D` flags,
then `make -j`.
3. **Run tests** execute `./test/etl_tests -v` (or `ctest -V` for 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
* `master`
* `development`
* `pull-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:
1. Runs `test/run-coverage.sh` which builds and tests with GCC coverage
flags.
2. Uploads the HTML report as a build artifact (retained for 30 days).
3. On pushes to `master`, deploys the report to **GitHub Pages**.
To generate coverage locally:
```bash
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](https://nedbatchelder.com/code/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
```bash
python3 scripts/generator_test.py
```
### What the script does
1. Iterates over every `*_generator.h` file in `include/etl/generators/`.
2. Runs Cog on each generator, outputting to `build/generator_tmp/`.
3. Compares each generated file against the corresponding file in
`include/etl/private/`.
4. 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.

View File

@ -558,7 +558,8 @@ namespace etl
{
while (first != last)
{
*first = value;
// This cast is necessary because the signedness can differ
*first = static_cast<typename etl::iterator_traits<TIterator>::value_type>(value);
++first;
}
}

View File

@ -404,7 +404,7 @@ namespace etl
//*************************************************************************
void read_commit(const span<T>& reserve)
{
size_type rindex = etl::distance(p_buffer, reserve.data());
size_type rindex = static_cast<size_type>(etl::distance(p_buffer, reserve.data()));
apply_read_reserve(rindex, reserve.size());
}
@ -438,7 +438,7 @@ namespace etl
//*************************************************************************
void write_commit(const span<T>& reserve)
{
size_type windex = etl::distance(p_buffer, reserve.data());
size_type windex = static_cast<size_type>(etl::distance(p_buffer, reserve.data()));
apply_write_reserve(windex, reserve.size());
}

View File

@ -644,7 +644,7 @@ namespace etl
// in debug.
#if ETL_IS_DEBUG_BUILD
// Is the address on a valid object boundary?
bool is_valid_address = ((distance % Item_Size) == 0);
bool is_valid_address = ((static_cast<size_t>(distance) % Item_Size) == 0);
#else
bool is_valid_address = true;
#endif

View File

@ -959,11 +959,16 @@ namespace etl
ETL_CONSTANT bool is_random_access_iterator_concept<T>::value;
#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED
#if ETL_CPP11_SUPPORTED
//*****************************************************************************
/// Get the 'begin' iterator.
/// Note: Contains SFINAE guard, ensuring they only participate in overload
/// resolution when TContainer actually has the corresponding member function.
/// This prevents ADL from matching these templates when std::ranges::begin
/// performs an unqualified call on etl:: iterator types.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<TContainer&>().begin())> >
ETL_CONSTEXPR typename TContainer::iterator begin(TContainer& container)
{
return container.begin();
@ -973,7 +978,7 @@ namespace etl
/// Get the 'begin' const_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().begin())> >
ETL_CONSTEXPR typename TContainer::const_iterator begin(const TContainer& container)
{
return container.begin();
@ -983,7 +988,7 @@ namespace etl
/// Get the 'begin' const_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().cbegin())> >
ETL_CONSTEXPR typename TContainer::const_iterator cbegin(const TContainer& container)
{
return container.cbegin();
@ -993,7 +998,7 @@ namespace etl
/// Get the 'end' iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<TContainer&>().end())> >
ETL_CONSTEXPR typename TContainer::iterator end(TContainer& container)
{
return container.end();
@ -1003,7 +1008,7 @@ namespace etl
/// Get the 'end' const_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().end())> >
ETL_CONSTEXPR typename TContainer::const_iterator end(const TContainer& container)
{
return container.end();
@ -1013,11 +1018,73 @@ namespace etl
/// Get the 'end' const_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().cend())> >
ETL_CONSTEXPR typename TContainer::const_iterator cend(const TContainer& container)
{
return container.cend();
}
#else
// C++03 fallback: no SFINAE guards needed since std::ranges does not exist.
//*****************************************************************************
/// Get the 'begin' iterator.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::iterator begin(TContainer& container)
{
return container.begin();
}
//*****************************************************************************
/// Get the 'begin' const_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::const_iterator begin(const TContainer& container)
{
return container.begin();
}
//*****************************************************************************
/// Get the 'begin' const_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::const_iterator cbegin(const TContainer& container)
{
return container.cbegin();
}
//*****************************************************************************
/// Get the 'end' iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::iterator end(TContainer& container)
{
return container.end();
}
//*****************************************************************************
/// Get the 'end' const_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::const_iterator end(const TContainer& container)
{
return container.end();
}
//*****************************************************************************
/// Get the 'end' const_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::const_iterator cend(const TContainer& container)
{
return container.cend();
}
#endif
//*****************************************************************************
/// Get the 'begin' pointer for an array.
@ -1081,11 +1148,13 @@ namespace etl
#endif
#if ETL_NOT_USING_STL || ETL_CPP14_NOT_SUPPORTED
#if ETL_CPP11_SUPPORTED
//*****************************************************************************
/// Get the 'begin' reverse_iterator for a container.
/// Note: Contains SFINAE guard (see begin/end above for rationale).
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<TContainer&>().rbegin())> >
ETL_CONSTEXPR typename TContainer::reverse_iterator rbegin(TContainer& container)
{
return container.rbegin();
@ -1095,7 +1164,7 @@ namespace etl
/// Get the 'begin' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().rbegin())> >
ETL_CONSTEXPR typename TContainer::const_reverse_iterator rbegin(const TContainer& container)
{
return container.rbegin();
@ -1105,7 +1174,7 @@ namespace etl
/// Get the 'begin' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().crbegin())> >
ETL_CONSTEXPR typename TContainer::const_reverse_iterator crbegin(const TContainer& container)
{
return container.crbegin();
@ -1115,7 +1184,7 @@ namespace etl
/// Get the 'end' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<TContainer&>().rend())> >
ETL_CONSTEXPR typename TContainer::reverse_iterator rend(TContainer& container)
{
return container.rend();
@ -1125,7 +1194,7 @@ namespace etl
/// Get the 'end' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().rend())> >
ETL_CONSTEXPR typename TContainer::const_reverse_iterator rend(const TContainer& container)
{
return container.rend();
@ -1135,11 +1204,73 @@ namespace etl
/// Get the 'end' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().crend())> >
ETL_CONSTEXPR typename TContainer::const_reverse_iterator crend(const TContainer& container)
{
return container.crend();
}
#else
// C++03 fallback: no SFINAE guards needed since std::ranges does not exist.
//*****************************************************************************
/// Get the 'begin' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::reverse_iterator rbegin(TContainer& container)
{
return container.rbegin();
}
//*****************************************************************************
/// Get the 'begin' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::const_reverse_iterator rbegin(const TContainer& container)
{
return container.rbegin();
}
//*****************************************************************************
/// Get the 'begin' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::const_reverse_iterator crbegin(const TContainer& container)
{
return container.crbegin();
}
//*****************************************************************************
/// Get the 'end' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::reverse_iterator rend(TContainer& container)
{
return container.rend();
}
//*****************************************************************************
/// Get the 'end' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::const_reverse_iterator rend(const TContainer& container)
{
return container.rend();
}
//*****************************************************************************
/// Get the 'end' reverse_iterator for a container.
///\ingroup container
//*****************************************************************************
template <typename TContainer>
typename TContainer::const_reverse_iterator crend(const TContainer& container)
{
return container.crend();
}
#endif
//*****************************************************************************
/// Get the 'begin' reverse_iterator for an array.

View File

@ -130,11 +130,11 @@ namespace etl
{
if (a > b)
{
return b + (etl::distance(b, a) / 2U);
return b + (etl::distance(b, a) / 2);
}
else
{
return a + (etl::distance(a, b) / 2U);
return a + (etl::distance(a, b) / 2);
}
}
@ -151,11 +151,11 @@ namespace etl
{
if (a > b)
{
return b + (etl::distance(b, a) / 2U);
return b + (etl::distance(b, a) / 2);
}
else
{
return a + (etl::distance(a, b) / 2U);
return a + (etl::distance(a, b) / 2);
}
}
@ -172,7 +172,7 @@ namespace etl
|| etl::is_same<typename etl::iterator_traits<T>::iterator_category, ETL_OR_STD::bidirectional_iterator_tag>::value)),
int>::type = 0)
{
etl::advance(a, etl::distance(a, b) / 2U);
etl::advance(a, etl::distance(a, b) / 2);
return a;
}

View File

@ -1078,7 +1078,7 @@ namespace etl
/// Extract an value from multiple elements.
//*************************************************************************
template <typename T>
static ETL_CONSTEXPR14 typename etl::make_unsigned<T>::type extract_from_multiple_elements(const element_type* pbuffer, int element_index,
static ETL_CONSTEXPR14 typename etl::make_unsigned<T>::type extract_from_multiple_elements(const element_type* pbuffer, size_t element_index,
size_t active_bits_in_msb, size_t length) ETL_NOEXCEPT
{
typedef typename etl::make_unsigned<T>::type unsigned_t;
@ -1133,8 +1133,8 @@ namespace etl
unsigned_t value(0);
const int Msb_Element_Index = (position + length - 1) >> etl::log2<Bits_Per_Element>::value;
const int Lsb_Element_Index = position >> etl::log2<Bits_Per_Element>::value;
const size_t Msb_Element_Index = (position + length - 1) >> etl::log2<Bits_Per_Element>::value;
const size_t Lsb_Element_Index = position >> etl::log2<Bits_Per_Element>::value;
// Is the value contained within one element?
if (Msb_Element_Index == Lsb_Element_Index)
@ -1150,7 +1150,7 @@ namespace etl
size_t active_bits_in_msb = (position + length) - (static_cast<size_t>(Msb_Element_Index) * Bits_Per_Element);
// Start with index of the element containing the msb.
int element_index = Msb_Element_Index;
size_t element_index = Msb_Element_Index;
value = extract_from_multiple_elements<T>(pbuffer, element_index, active_bits_in_msb, length);
}
@ -1169,7 +1169,7 @@ namespace etl
{
typedef typename etl::make_unsigned<T>::type unsigned_t;
const int Element_Index = (Position + Length - 1) >> etl::log2<Bits_Per_Element>::value;
const size_t Element_Index = (Position + Length - 1) >> etl::log2<Bits_Per_Element>::value;
const unsigned_t Mask = etl::lsb_mask<unsigned_t, Length>::value;
const unsigned_t Shift = Position % Bits_Per_Element;
@ -1186,7 +1186,7 @@ namespace etl
extract_from_buffer(const_pointer pbuffer)
{
// Start with index of the element containing the msb.
const int Msb_Element_Index = (Position + Length - 1) >> etl::log2<Bits_Per_Element>::value;
const size_t Msb_Element_Index = (Position + Length - 1) >> etl::log2<Bits_Per_Element>::value;
// Get the number of active bits in the first element
const size_t Active_Bits_In_Msb = ((Position + Length - 1) % Bits_Per_Element) + 1;

View File

@ -0,0 +1,44 @@
///\file
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2025 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
/*
* The header include guard has been intentionally omitted.
* This file is intended to evaluated multiple times by design.
*/
#if defined(__GNUC__) && !defined(__clang__) && !defined(__llvm__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#if defined(__clang__) || defined(__llvm__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wsign-conversion"
#endif

View File

@ -479,7 +479,9 @@ namespace etl
{
ETL_ASSERT_CHECK_PUSH_POP(size() != CAPACITY, ETL_ERROR(vector_full));
#include "private/diagnostic_sign_conversion_push.h"
::new (p_end) T(etl::forward<Args>(args)...);
#include "private/diagnostic_pop.h"
++p_end;
ETL_INCREMENT_DEBUG_COUNT;
return back();
@ -668,7 +670,9 @@ namespace etl
(*position_).~T();
}
#include "private/diagnostic_sign_conversion_push.h"
::new (p) T(etl::forward<Args>(args)...);
#include "private/diagnostic_pop.h"
return position_;
}

View File

@ -385,6 +385,7 @@ option(ETL_NO_STL "No STL" OFF)
set(EXTRA_COMPILE_OPTIONS "" CACHE STRING "Additional compiler options")
set(EXTRA_LINK_OPTIONS "" CACHE STRING "Additional linker options")
set(EXTRA_LINK_LIBS "" CACHE STRING "Additional libraries to link")
set(EXTRA_TESTING_FLAGS "" CACHE STRING "Additional testing flags for ctest")
if (ETL_CXX_STANDARD MATCHES "98")
message(STATUS "Compiling for C++98")
@ -538,7 +539,7 @@ target_link_libraries(etl_tests PRIVATE UnitTestpp ${EXTRA_LINK_LIBS})
enable_testing()
# Enable the 'make test' CMake target using the executable defined above
add_test(NAME etl_unit_tests COMMAND etl_tests)
add_test(NAME etl_unit_tests COMMAND etl_tests ${EXTRA_TESTING_FLAGS})
# Since ctest will only show you the results of the single executable
# define a target that will output all of the failing or passing tests

View File

@ -2,6 +2,8 @@
shopt -s xpg_echo
set -e
clear
export ASAN_OPTIONS=symbol_line=1
@ -54,7 +56,7 @@ PrintHelp()
echo "$HelpColour"
echo "----------------------------------------------------------------------------------------------------------"
echo " Syntax : ./run-tests.sh <C++ Standard> <Optimisation> <Threads> <Sanitizer> <Compiler> <Verbose>"
echo " C++ Standard : 11, 14, 17, 20 or 23 "
echo " C++ Standard : 11, 14, 17, 20, 23 or all "
echo " Optimisation : 0, 1, 2 or 3. Default = 0 "
echo " Threads : Number of threads to use. Default = 4 "
echo " Sanitizer : s enables sanitizer checks, n disables. Default disabled "
@ -115,15 +117,17 @@ TestsCompleted()
# Set the language standard.
#******************************************************************************
if [ "$1" = "11" ]; then
cxx_standard="11"
cxx_standards="11"
elif [ "$1" = "14" ]; then
cxx_standard="14"
cxx_standards="14"
elif [ "$1" = "17" ]; then
cxx_standard="17"
cxx_standards="17"
elif [ "$1" = "20" ]; then
cxx_standard="20"
cxx_standards="20"
elif [ "$1" = "23" ]; then
cxx_standard="23"
cxx_standards="23"
elif [ "$1" = "all" ]; then
cxx_standards="11 14 17 20 23"
else
PrintHelp
exit
@ -180,10 +184,10 @@ fi
#******************************************************************************
if [ "$6" = "v" ]; then
verbose="On"
verbose_flag="-v"
verbose_cmake_flag="-DEXTRA_TESTING_FLAGS=-v"
else
verbose="Off"
verbose_flag=""
verbose_cmake_flag=""
fi
#******************************************************************************
@ -196,66 +200,66 @@ etl_version=$(echo $etl_version_raw | sed -e 's/\r//g') # Remove trailing \r
# Get the compiler versions
#******************************************************************************
while read i ; do
CC=`echo $i | cut -d, -f1 | sed -e 's/ *$//'`
MSG=`echo $i | cut -d, -f2 | sed -e 's/ *$//'`
DIR=`echo $i | cut -d, -f3 | sed -e 's/ *$//'`
CMD=`echo $i | cut -d, -f4 | sed -e 's/ *$//'`
for cxx_standard in $cxx_standards ; do
while read i ; do
CC=`echo $i | cut -d, -f1 | sed -e 's/ *$//'`
MSG=`echo $i | cut -d, -f2 | sed -e 's/ *$//'`
DIR=`echo $i | cut -d, -f3 | sed -e 's/ *$//'`
CMD=`echo $i | cut -d, -f4 | sed -e 's/ *$//'`
if [ "$compiler_enabled" = "$CC" ] || [ "$compiler_enabled" = "All compilers" ]; then
if [ "$CC" = "gcc" ] ; then
compiler=$(g++ --version | grep g++)
else
compiler=$(clang++ --version | grep clang)
if [ "$compiler_enabled" = "$CC" ] || [ "$compiler_enabled" = "All compilers" ]; then
if [ "$CC" = "gcc" ] ; then
compiler=$(g++ --version | grep g++)
else
compiler=$(clang++ --version | grep clang)
fi
OLD_DIR=`pwd`
cd $DIR
mkdir -p build-make || exit 1
cd build-make || exit 1
echo "ETL Tests" > log.txt
SetConfigurationName "$MSG"
PrintHeader
$CMD
if cmake --build .; then
PassedCompilation
else
FailedCompilation
exit 1
fi
if ctest -V; then
PassedTests
else
FailedTests
exit 1
fi
cd ..
rm -rf build-make
cd $OLD_DIR
fi
OLD_DIR=`pwd`
cd $DIR
mkdir -p build-make || exit 1
cd build-make || exit 1
echo "ETL Tests" > log.txt
SetConfigurationName "$MSG"
PrintHeader
$CMD
cmake --build .
if [ $? -eq 0 ]; then
PassedCompilation
else
FailedCompilation
exit $?
fi
./etl_tests $verbose_flag
if [ $? -eq 0 ]; then
PassedTests
else
FailedTests
exit $?
fi
cd ..
rm -rf build-make
cd $OLD_DIR
fi
done <<-EOF
gcc ,STL ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF ..
gcc ,STL - Non-virtual messages,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=ON ..
gcc ,STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF ..
gcc ,No STL ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF ..
gcc ,No STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF ..
gcc ,No STL - Builtin mem functions ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF -DETL_USE_BUILTIN_MEM_FUNCTIONS=ON ..
clang,STL ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF ..
clang,STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF ..
clang,No STL ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF ..
clang,No STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF ..
clang,No STL - Builtin mem functions ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF -DETL_USE_BUILTIN_MEM_FUNCTIONS=ON ..
gcc ,Initializer list test ,etl_initializer_list,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize ..
clang,Initializer list test ,etl_initializer_list,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize ..
gcc ,Error macros 'log_errors' test,etl_error_handler/log_errors ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize ..
gcc ,Error macros 'exceptions' test,etl_error_handler/exceptions ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize ..
gcc ,Error macros 'log_errors and exceptions' test,etl_error_handler/log_errors_and_exceptions,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize ..
gcc ,Error macros 'assert function' test,etl_error_handler/assert_function ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize ..
clang,Error macros 'log_errors' test,etl_error_handler/log_errors ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize ..
clang,Error macros 'exceptions' test,etl_error_handler/exceptions ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize ..
clang,Error macros 'log_errors and exceptions' test,etl_error_handler/log_errors_and_exceptions,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize ..
clang,Error macros 'assert function' test,etl_error_handler/assert_function ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize ..
done <<-EOF
gcc ,STL ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag ..
gcc ,STL - Non-virtual messages,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=ON $verbose_cmake_flag ..
gcc ,STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag ..
gcc ,No STL ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag ..
gcc ,No STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag ..
gcc ,No STL - Builtin mem functions ,.,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF -DETL_USE_BUILTIN_MEM_FUNCTIONS=ON $verbose_cmake_flag ..
clang,STL ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag ..
clang,STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag ..
clang,No STL ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag ..
clang,No STL - Force C++03 ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF $verbose_cmake_flag ..
clang,No STL - Builtin mem functions ,.,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize -DETL_MESSAGES_ARE_NOT_VIRTUAL=OFF -DETL_USE_BUILTIN_MEM_FUNCTIONS=ON $verbose_cmake_flag ..
gcc ,Initializer list test ,etl_initializer_list,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag ..
clang,Initializer list test ,etl_initializer_list,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag ..
gcc ,Error macros 'log_errors' test,etl_error_handler/log_errors ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag ..
gcc ,Error macros 'exceptions' test,etl_error_handler/exceptions ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag ..
gcc ,Error macros 'log_errors and exceptions' test,etl_error_handler/log_errors_and_exceptions,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag ..
gcc ,Error macros 'assert function' test,etl_error_handler/assert_function ,cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag ..
clang,Error macros 'log_errors' test,etl_error_handler/log_errors ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag ..
clang,Error macros 'exceptions' test,etl_error_handler/exceptions ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag ..
clang,Error macros 'log_errors and exceptions' test,etl_error_handler/log_errors_and_exceptions,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag ..
clang,Error macros 'assert function' test,etl_error_handler/assert_function ,cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DETL_OPTIMISATION=$opt -DETL_CXX_STANDARD=$cxx_standard -DETL_ENABLE_SANITIZER=$sanitize $verbose_cmake_flag ..
EOF
done
TestsCompleted

View File

@ -869,7 +869,7 @@ namespace
TEST(put_get_multiple_full_size)
{
char c1 = 90;
char c2 = -91;
char c2 = static_cast<char>(-91);
unsigned short s1 = 23205;
unsigned short s2 = 42330;
int32_t i1 = 1520786085L; // 0x5AA55AA5

View File

@ -614,7 +614,7 @@ namespace
TEST(test_write_multiple_full_size)
{
char c1 = 90; // 0x5A
char c2 = -91; // 0xA5
char c2 = static_cast<char>(-91); // 0xA5
unsigned short s1 = 4660; // 0x1234
unsigned short s2 = 22136; // 0x5678
int32_t i1 = static_cast<int32_t>(0x89ABCDEFU); // 0x89ABCDEF
@ -660,7 +660,7 @@ namespace
TEST(test_write_multiple_variable_size)
{
char c1 = 90; // 0x5A 6 bits
char c2 = -91; // 0xA5 7 bits
char c2 = static_cast<char>(-91); // 0xA5 7 bits
unsigned short s1 = 4660; // 0x1234 13 bits
unsigned short s2 = 22136; // 0x5678 11 bits
int32_t i1 = static_cast<int32_t>(0x89ABCDEFU); // 0x89ABCDEF 23 bits
@ -705,7 +705,7 @@ namespace
Accumulator accumulator;
char c1 = 90; // 0x5A 6 bits
char c2 = -91; // 0xA5 7 bits
char c2 = static_cast<char>(-91); // 0xA5 7 bits
unsigned short s1 = 4660U; // 0x1234 13 bits
unsigned short s2 = 22136U; // 0x5678 11 bits
int32_t i1 = static_cast<int32_t>(0x89ABCDEFU); // 0x89ABCDEF 23 bits

View File

@ -702,7 +702,7 @@ namespace
TEST(test_write_multiple_full_size)
{
char c1 = 90; // 0x5A
char c2 = -91; // 0xA5
char c2 = static_cast<char>(-91); // 0xA5
unsigned short s1 = 4660; // 0x1234
unsigned short s2 = 22136; // 0x5678
int32_t i1 = static_cast<int32_t>(0x89ABCDEFU); // 0x89ABCDEF
@ -748,7 +748,7 @@ namespace
TEST(test_write_multiple_variable_size)
{
char c1 = 90; // 0x5A 6 bits
char c2 = -91; // 0xA5 7 bits
char c2 = static_cast<char>(-91); // 0xA5 7 bits
unsigned short s1 = 4660; // 0x1234 13 bits
unsigned short s2 = 22136; // 0x5678 11 bits
int32_t i1 = static_cast<int32_t>(0x89ABCDEFU); // 0x89ABCDEF 23 bits
@ -791,7 +791,7 @@ namespace
TEST(test_write_multiple_variable_size_with_callback)
{
char c1 = 90; // 0x5A 6 bits
char c2 = -91; // 0xA5 7 bits
char c2 = static_cast<char>(-91); // 0xA5 7 bits
unsigned short s1 = 4660; // 0x1234 13 bits
unsigned short s2 = 22136; // 0x5678 11 bits
int32_t i1 = static_cast<int32_t>(0x89ABCDEFU); // 0x89ABCDEF 23 bits

View File

@ -1026,7 +1026,7 @@ namespace
TEST(write_read_multiple_big_endian)
{
char c1 = 90;
char c2 = -91;
char c2 = static_cast<char>(-91);
unsigned short s1 = 23205;
unsigned short s2 = 42330;
int32_t i1 = 1520786085; // 0x5AA55AA5
@ -1089,7 +1089,7 @@ namespace
TEST(write_read_multiple_little_endian)
{
char c1 = 90;
char c2 = -91;
char c2 = static_cast<char>(-91);
unsigned short s1 = 23205;
unsigned short s2 = 42330;
int32_t i1 = 1520786085; // 0x5AA55AA5

View File

@ -214,7 +214,7 @@ namespace
etl::string<100> s;
CHECK_EQUAL("1.0", test_format(s, "{}", 1.0));
CHECK_EQUAL("1.234564", test_format(s, "{}", 1.234564));
CHECK_EQUAL("1.234563", test_format(s, "{}", 1.234563));
CHECK_EQUAL("1.234567", test_format(s, "{}", 1.2345678));
CHECK_EQUAL("1.5", test_format(s, "{}", 1.5));
}

View File

@ -149,7 +149,14 @@ namespace
if (ETL_PLATFORM_32BIT)
{
CHECK_EQUAL(0xEC6A8D69UL, hash);
if (etl::endianness::value() == etl::endian::little)
{
CHECK_EQUAL(0xEC6A8D69UL, hash);
}
else
{
CHECK_EQUAL(0x5F69FD19UL, hash);
}
}
if (ETL_PLATFORM_64BIT)
@ -165,7 +172,14 @@ namespace
if (ETL_PLATFORM_32BIT)
{
CHECK_EQUAL(0xEC6A8D69UL, hash);
if (etl::endianness::value() == etl::endian::little)
{
CHECK_EQUAL(0xEC6A8D69UL, hash);
}
else
{
CHECK_EQUAL(0x5F69FD19UL, hash);
}
}
if (ETL_PLATFORM_64BIT)
@ -177,7 +191,7 @@ namespace
//*************************************************************************
TEST(test_hash_float)
{
size_t hash = etl::hash<float>()((float)(1.2345));
size_t hash = etl::hash<float>()(1.2345f);
if (ETL_PLATFORM_32BIT)
{
@ -204,7 +218,14 @@ namespace
if (ETL_PLATFORM_32BIT)
{
CHECK_EQUAL(0x86FBF224UL, hash);
if (etl::endianness::value() == etl::endian::little)
{
CHECK_EQUAL(0x86FBF224UL, hash);
}
else
{
CHECK_EQUAL(0xD1F372DEUL, hash);
}
}
if (ETL_PLATFORM_64BIT)

View File

@ -166,7 +166,7 @@ namespace
for (size_t i = 0UL; i < output1.size(); ++i)
{
CHECK_EQUAL(int(output1[i]), int(histogram[i]));
CHECK_EQUAL(static_cast<int>(output1[i]), static_cast<int>(histogram[static_cast<int>(i)]));
}
}
@ -203,7 +203,7 @@ namespace
for (size_t i = 0UL; i < output1.size(); ++i)
{
CHECK_EQUAL(int(output1[i]), int(histogram[i - 4]));
CHECK_EQUAL(static_cast<int>(output1[i]), static_cast<int>(histogram[static_cast<int>(i) - 4]));
}
}

View File

@ -594,8 +594,8 @@ namespace
for (size_t i = 0; i < MAX_SIZE; ++i)
{
data_result = data.insert(i);
compare_result = compare_data.insert(i);
data_result = data.insert(static_cast<int>(i));
compare_result = compare_data.insert(static_cast<int>(i));
// Check that both return successful return results
CHECK_EQUAL(*data_result.first, *compare_result.first);
@ -608,8 +608,8 @@ namespace
// not throw error
for (size_t i = 0; i < MAX_SIZE; ++i)
{
data_result = data.insert(i);
compare_result = compare_data.insert(i);
data_result = data.insert(static_cast<int>(i));
compare_result = compare_data.insert(static_cast<int>(i));
// Check that both return successful return results
CHECK_EQUAL(*data_result.first, *compare_result.first);