pax_global_header 0000666 0000000 0000000 00000000064 14773232535 0014525 g ustar 00root root 0000000 0000000 52 comment=f923e6fe4b7542d75e0c4ee54ad0af6a5382a87c
boost-ext-ut-2.3.1/ 0000775 0000000 0000000 00000000000 14773232535 0014102 5 ustar 00root root 0000000 0000000 boost-ext-ut-2.3.1/.clang-format 0000664 0000000 0000000 00000000167 14773232535 0016461 0 ustar 00root root 0000000 0000000 Language: Cpp
Standard: Cpp11
BasedOnStyle: Google
ReflowComments: false
boost-ext-ut-2.3.1/.clang-tidy 0000664 0000000 0000000 00000001304 14773232535 0016134 0 ustar 00root root 0000000 0000000 ---
Checks: "-*,\
boost-*,\
-cert-*,\
clang-analyzer-*,\
-cppcoreguidelines-*,\
-hicpp-*,\
hicpp-exception-baseclass,\
hicpp-no-array-decay,\
misc-*,\
-misc-no-recursion,\
-misc-non-private-member-variables-in-classes,\
-misc-redundant-expression,\
-misc-unconventional-assign-operator,\
modernize-*,\
-modernize-pass-by-value,\
-modernize-use-trailing-return-type,\
performance-*,\
-performance-avoid-endl,\
portability-*,\
readability-*,\
-readability-identifier-length,\
-readability-redundant-member-init,\
-*implicit-bool-conversion,\
-*magic-numbers,\
-*named-parameter,\
-*uppercase-literal-suffix,\
"
WarningsAsErrors: ''
HeaderFilterRegex: '.*'
FormatStyle: file
User: clausklein
...
boost-ext-ut-2.3.1/.cmake-format.py 0000664 0000000 0000000 00000001736 14773232535 0017107 0 ustar 00root root 0000000 0000000 # See https://cmake-format.readthedocs.io/en/latest/configuration.html for all options
# -----------------------------
# Options affecting formatting.
# -----------------------------
with section("format"):
# Disable formatting entirely, making cmake-format a no-op
disable = False
# How wide to allow formatted cmake files
line_width = 135
# How many spaces to tab for indent
tab_size = 2
# If a statement is wrapped to more than one line, than dangle the closing
# parenthesis on its own line.
dangle_parens = True
# ------------------------------------------------
# Options affecting comment reflow and formatting.
# ------------------------------------------------
with section("markup"):
# enable comment markup parsing and reflow
enable_markup = False
# ----------------------------
# Options affecting the linter
# ----------------------------
with section("lint"):
# a list of lint codes to disable
disabled_codes = ['C0111']
boost-ext-ut-2.3.1/.github/ 0000775 0000000 0000000 00000000000 14773232535 0015442 5 ustar 00root root 0000000 0000000 boost-ext-ut-2.3.1/.github/CONTRIBUTING.md 0000664 0000000 0000000 00000002054 14773232535 0017674 0 ustar 00root root 0000000 0000000 # How to contribute
Contributions are always very much appreciated. However, to make sure the
process of accepting patches goes smoothly for everyone (especially for
the maintainer), you should try to follow these few simple guidelines when
you contribute:
1. Fork the repository.
2. Create a new branch based on the `master` branch (`git checkout -b your_branch master`).
3. Do your modifications on that branch.
4. Be sure your modifications include:
* Don't break anything (`make`)
* Proper unit/functional tests (`make test`)
* Verify performance (`make benchmark`)
5. Commit your changes. Your commit message should reflect your changes.
6. Push the changes to your fork (`git push origin your_branch`).
7. Rebase if necessary to avoid broken commits (`git rebase -i origin/master`).
8. Open a pull request against UT's `master` branch.
I will do my best to respond in a timely manner.
I might discuss your patch and suggest some modifications, or I might amend your patch myself and ask you for feedback.
You will always be given proper credit.
boost-ext-ut-2.3.1/.github/ISSUE_TEMPLATE.md 0000664 0000000 0000000 00000000232 14773232535 0020144 0 ustar 00root root 0000000 0000000 ## Expected Behavior
## Actual Behavior
## Steps to Reproduce the Problem
1.
1.
1.
## Specifications
- Version:
- Platform:
- Subsystem:
boost-ext-ut-2.3.1/.github/PULL_REQUEST_TEMPLATE.md 0000664 0000000 0000000 00000000060 14773232535 0021237 0 ustar 00root root 0000000 0000000 Problem:
-
Solution:
-
Issue: #
Reviewers:
@
boost-ext-ut-2.3.1/.github/workflows/ 0000775 0000000 0000000 00000000000 14773232535 0017477 5 ustar 00root root 0000000 0000000 boost-ext-ut-2.3.1/.github/workflows/emscripten.yml 0000664 0000000 0000000 00000003141 14773232535 0022372 0 ustar 00root root 0000000 0000000 ---
name: Emscripten
on:
push:
branches:
- master
- develop
pull_request:
branches:
- master
- develop
env:
CTEST_OUTPUT_ON_FAILURE: 1
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# - uses: actions/cache@v3
# with:
# path: "**/cpm_modules"
# key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
- name: Install emscripten
run: |
cd
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
# Download and install the latest SDK tools.
./emsdk install releases-03ecb526947f6a3702a0d083083799fe410d3893-64bit
# Make the "latest" SDK "active" for the current user. (writes .emscripten file)
./emsdk activate releases-03ecb526947f6a3702a0d083083799fe410d3893-64bit
# Activate PATH and other environment variables in the current terminal
source ./emsdk_env.sh
- name: configure
run: |
source ~/emsdk/emsdk_env.sh
emcmake cmake -S . -B build -DCMAKE_CXX_STANDARD=17 -DCMAKE_BUILD_TYPE=Debug -DBOOST_UT_ENABLE_RUN_AFTER_BUILD=NO --log-level=DEBUG -DFETCHCONTENT_QUIET=OFF
- name: build
run: |
source ~/emsdk/emsdk_env.sh
cmake --build build -j4 --verbose
- name: test
run: |
source ~/emsdk/emsdk_env.sh
cd build
ctest --build-config Debug -j4 --verbose
boost-ext-ut-2.3.1/.github/workflows/install.yml 0000664 0000000 0000000 00000002447 14773232535 0021677 0 ustar 00root root 0000000 0000000 ---
name: Install
on:
push:
branches:
- master
- develop
pull_request:
branches:
- master
- develop
env:
CTEST_OUTPUT_ON_FAILURE: 1
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: "**/cpm_modules"
key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
# - name: install ninja
# sudo apt-get install ninja-build
- name: build and install library
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBOOST_UT_ENABLE_RUN_AFTER_BUILD=NO -DBOOST_UT_ENABLE_INSTALL=ON --log-level=DEBUG -DFETCHCONTENT_QUIET=OFF
cmake --build build --target all -j4 --verbose
cmake --install build --prefix ./install_dir
rm -rf build
- name: configure
run: CMAKE_PREFIX_PATH="./install_dir" cmake -S test -B build -DTEST_INSTALLED_VERSION=1 -DBOOST_UT_ENABLE_RUN_AFTER_BUILD=NO --log-level=DEBUG -DFETCHCONTENT_QUIET=OFF
- name: build
run: cmake --build build --config Debug -j4 --verbose
- name: test
run: |
cd build
ctest --build-config Debug -j4 --verbose
boost-ext-ut-2.3.1/.github/workflows/install_download_all.yml 0000664 0000000 0000000 00000002474 14773232535 0024416 0 ustar 00root root 0000000 0000000 ---
name: Install
on:
push:
branches:
- master
- develop
pull_request:
branches:
- master
- develop
env:
CTEST_OUTPUT_ON_FAILURE: 1
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: "**/cpm_modules"
key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
# - name: install ninja
# sudo apt-get install ninja-build
- name: build and install library
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCPM_DOWNLOAD_ALL=1 -DBOOST_UT_ENABLE_RUN_AFTER_BUILD=NO -DBOOST_UT_ENABLE_INSTALL=ON --log-level=DEBUG -DFETCHCONTENT_QUIET=OFF
cmake --build build --target all -j4 --verbose
cmake --install build --prefix ./install_dir
rm -rf build
- name: configure
run: CMAKE_PREFIX_PATH="./install_dir" cmake -S test -B build -DTEST_INSTALLED_VERSION=1 -DBOOST_UT_ENABLE_RUN_AFTER_BUILD=NO --log-level=DEBUG -DFETCHCONTENT_QUIET=OFF
- name: build
run: cmake --build build --config Debug -j4 --verbose
- name: test
run: |
cd build
ctest --build-config Debug -j4 --verbose
boost-ext-ut-2.3.1/.github/workflows/linux.yml 0000664 0000000 0000000 00000001556 14773232535 0021370 0 ustar 00root root 0000000 0000000 ---
name: Linux
on:
push:
branches:
- master
- develop
pull_request:
branches:
- master
- develop
env:
CTEST_OUTPUT_ON_FAILURE: 1
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: "**/cpm_modules"
key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
- name: configure
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBOOST_UT_ENABLE_RUN_AFTER_BUILD=NO --log-level=DEBUG -DFETCHCONTENT_QUIET=OFF
- name: build
run: cmake --build build -j4 --verbose
- name: test
run: |
cd build
ctest --build-config Debug -j4 --verbose
boost-ext-ut-2.3.1/.github/workflows/macos.yml 0000664 0000000 0000000 00000002676 14773232535 0021337 0 ustar 00root root 0000000 0000000 ---
name: MacOS
on:
push:
branches:
- master
- develop
pull_request:
branches:
- master
- develop
env:
CTEST_OUTPUT_ON_FAILURE: 1
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules
jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: "**/cpm_modules"
key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
- name: Install ninja and python
shell: bash
run: brew install llvm clang-format ninja python pipx
- name: Install builddriver
shell: bash
run:
pipx install builddriver cmake_format==0.6.11 pyaml
- name: configure
shell: bash
run: |
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBOOST_UT_ENABLE_RUN_AFTER_BUILD=NO \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON --log-level=DEBUG -DFETCHCONTENT_QUIET=OFF
- name: build
run: cmake --build build -j4 --verbose
- name: test
shell: bash
run: |
cd build
ctest --build-config Debug -j4 --verbose
- name: Run clang-tidy
shell: bash
run: |
export PATH=$(brew --prefix llvm)/bin:${PATH}
$(brew --prefix llvm)/bin/run-clang-tidy \
-p build test 2>&1 | tee .run-clang-tidy.log
builddriver cat .run-clang-tidy.log
boost-ext-ut-2.3.1/.github/workflows/windows.yml 0000664 0000000 0000000 00000002050 14773232535 0021711 0 ustar 00root root 0000000 0000000 ---
name: Windows
on:
push:
branches:
- master
- develop
pull_request:
branches:
- master
- develop
env:
CTEST_OUTPUT_ON_FAILURE: 1
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
toolset: [ClangCl, v143]
std: [20]
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: "**/cpm_modules"
key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
- name: configure
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBOOST_UT_ENABLE_RUN_AFTER_BUILD=NO -DBOOST_UT_DISABLE_MODULE=ON --log-level=DEBUG -DFETCHCONTENT_QUIET=OFF -G "Visual Studio 17 2022" -T ${{matrix.toolset}} -DCMAKE_CXX_STANDARD:STRING=${{matrix.std}}
- name: build
run: cmake --build build --config Debug -j4 --verbose
- name: test
run: |
cd build
ctest --build-config Debug -j4 --verbose
boost-ext-ut-2.3.1/.github/workflows/windows_shared.yml 0000664 0000000 0000000 00000002106 14773232535 0023241 0 ustar 00root root 0000000 0000000 ---
name: Windows_shared
on:
push:
branches:
- master
- develop
pull_request:
branches:
- master
- develop
env:
CTEST_OUTPUT_ON_FAILURE: 1
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm_modules
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
toolset: [ClangCl, v143]
std: [20]
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: "**/cpm_modules"
key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
- name: configure
run: |
cmake -S . -B build -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Debug -DBOOST_UT_ENABLE_RUN_AFTER_BUILD=NO -DBOOST_UT_DISABLE_MODULE=ON --log-level=DEBUG -DFETCHCONTENT_QUIET=OFF -G "Visual Studio 17 2022" -T ${{matrix.toolset}} -DCMAKE_CXX_STANDARD:STRING=${{matrix.std}}
- name: build
run: cmake --build build --config Debug -j4 --verbose
- name: test
run: |
cd build
ctest --build-config Debug -j4 --verbose
boost-ext-ut-2.3.1/.gitignore 0000664 0000000 0000000 00000000157 14773232535 0016075 0 ustar 00root root 0000000 0000000 build*
/CMakeSettings.json
/.vs
/checks.json
/.vscode
install_dir/
cmake_build*/
compile_commands.json
.cache/
boost-ext-ut-2.3.1/.pre-commit-config.yaml 0000664 0000000 0000000 00000001646 14773232535 0020372 0 ustar 00root root 0000000 0000000 # See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
default_stages: [pre-commit]
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v19.1.7
hooks:
- id: clang-format
types_or: [c, c++]
exclude: .github
- repo: https://github.com/cheshirekow/cmake-format-precommit
rev: v0.6.13
hooks:
- id: cmake-format
args: [-i]
- id: cmake-lint
exclude: cmake/PackageProject.cmake
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: check-added-large-files
- id: check-case-conflict
- id: mixed-line-ending
args: [--fix=lf]
- id: end-of-file-fixer
- id: check-yaml
- id: check-xml
- id: check-json
- id: check-toml
- id: check-symlinks
- id: debug-statements
- id: fix-byte-order-marker
boost-ext-ut-2.3.1/CMakeLists.txt 0000664 0000000 0000000 00000007777 14773232535 0016664 0 ustar 00root root 0000000 0000000 #
# Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
option(BOOST_UT_DISABLE_MODULE "Disable ut module" ON)
if(NOT BOOST_UT_DISABLE_MODULE)
cmake_minimum_required(VERSION 4.0.0)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "a9e1cf81-9932-4810-974b-6eccaf14e457")
set(CMAKE_CXX_MODULE_STD 1)
else()
cmake_minimum_required(VERSION 3.21...3.25)
endif()
project(
ut
VERSION 2.3.1
LANGUAGES CXX
)
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD
20
CACHE STRING "Default value for CXX_STANDARD property of targets."
)
option(CMAKE_CXX_STANDARD_REQUIRED "Default value for CXX_STANDARD_REQUIRED property of targets." YES)
option(CMAKE_CXX_EXTENSIONS "Default value for CXX_EXTENSIONS property of targets." NO)
endif()
option(BOOST_UT_ENABLE_MEMCHECK "Run the unit tests and examples under valgrind if it is found" OFF)
option(BOOST_UT_ENABLE_COVERAGE "Run coverage" OFF)
option(BOOST_UT_ENABLE_SANITIZERS "Build with sanitizers" OFF)
option(BOOST_UT_BUILD_BENCHMARKS "Build the benchmarks" OFF)
option(BOOST_UT_BUILD_EXAMPLES "Build the examples" ${PROJECT_IS_TOP_LEVEL})
option(BOOST_UT_BUILD_TESTS "Build the tests" ${PROJECT_IS_TOP_LEVEL})
option(BOOST_UT_ENABLE_INSTALL "Enable install targets" ${PROJECT_IS_TOP_LEVEL})
option(BOOST_UT_USE_WARNINGS_AS_ERORS "Build the tests" ${PROJECT_IS_TOP_LEVEL})
add_library(ut INTERFACE)
if(NOT BOOST_UT_DISABLE_MODULE)
add_library(ut_module)
endif()
target_include_directories(ut INTERFACE $)
target_compile_features(ut INTERFACE cxx_std_20)
if(NOT BOOST_UT_DISABLE_MODULE)
target_compile_features(ut_module INTERFACE cxx_std_23)
endif()
if(BOOST_UT_USE_WARNINGS_AS_ERORS)
include(cmake/WarningsAsErrors.cmake)
endif()
add_custom_target(style COMMENT "Running clang-format")
add_custom_command(
TARGET style
POST_BUILD
COMMAND find ${CMAKE_CURRENT_LIST_DIR}/benchmark ${CMAKE_CURRENT_LIST_DIR}/example ${CMAKE_CURRENT_LIST_DIR}/include
${CMAKE_CURRENT_LIST_DIR}/test -iname "*.hpp" -or -iname "*.cpp" | xargs clang-format -i
COMMENT "Running clang-format"
)
if(BOOST_UT_ENABLE_COVERAGE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb3 -O0")
endif()
if(BOOST_UT_ENABLE_SANITIZERS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -fno-omit-frame-pointer
-fsanitize=address,leak,undefined"
)
endif()
if(BOOST_UT_DISABLE_MODULE)
target_compile_definitions(ut INTERFACE BOOST_UT_DISABLE_MODULE)
endif()
if(NOT BOOST_UT_DISABLE_MODULE)
target_sources(ut_module PUBLIC FILE_SET CXX_MODULES FILES include/boost/ut.cppm)
endif()
if(NOT TARGET Boost::ut)
add_library(Boost::ut ALIAS ut)
endif()
if(NOT BOOST_UT_DISABLE_MODULE)
add_library(Boost::ut_module ALIAS ut_module)
endif()
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
install(
FILES include/boost/ut.hpp include/boost/ut.cppm
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/boost
)
install(
TARGETS ut
EXPORT ut_Targets
INCLUDES DESTINATION include
)
install(
EXPORT ut_Targets
FILE utConfig.cmake
NAMESPACE Boost::
DESTINATION lib/cmake/ut
)
write_basic_package_version_file(
"utConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
ARCH_INDEPENDENT
)
install(
FILES "${PROJECT_BINARY_DIR}/utConfigVersion.cmake"
DESTINATION lib/cmake/ut
)
if(EMSCRIPTEN)
set(CMAKE_EXECUTABLE_SUFFIX ".js")
target_link_options(ut INTERFACE "SHELL:-s ALLOW_MEMORY_GROWTH=1" "SHELL:-s EXIT_RUNTIME=1" -fwasm-exceptions -g)
target_compile_options(ut INTERFACE -fwasm-exceptions -g)
endif()
# Note: now we can use the target Boost::ut
include(cmake/AddCustomCommandOrTest.cmake)
if(BOOST_UT_BUILD_BENCHMARKS)
add_subdirectory(benchmark)
endif()
if(BOOST_UT_BUILD_EXAMPLES)
add_subdirectory(example)
endif()
if(BOOST_UT_BUILD_TESTS)
enable_testing()
add_subdirectory(test)
endif()
boost-ext-ut-2.3.1/LICENSE.md 0000664 0000000 0000000 00000002472 14773232535 0015513 0 ustar 00root root 0000000 0000000 Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
boost-ext-ut-2.3.1/README.md 0000664 0000000 0000000 00000163640 14773232535 0015373 0 ustar 00root root 0000000 0000000 






> "If you liked it then you `"should have put a"_test` on it", Beyonce rule
# UT / Ξt
| [Motivation](#motivation) | [Quick Start](#quick-start) | [Overview](#overview) | [Tutorial](#tutorial) | [Examples](#examples) | [User Guide](#user-guide) | [FAQ](#faq) | [Benchmarks](#benchmarks) |
C++ single header/single module, macro-free Ξ(micro)/Unit Testing Framework
```cpp
#include // import boost.ut;
constexpr auto sum(auto... values) { return (values + ...); }
int main() {
using namespace boost::ut;
"sum"_test = [] {
expect(sum(0) == 0_i);
expect(sum(1, 2) == 3_i);
expect(sum(1, 2) > 0_i and 41_i == sum(40, 2));
};
}
```
```sh
Running "sum"...
sum.cpp:11:FAILED [(3 > 0 and 41 == 42)]
FAILED
===============================================================================
tests: 1 | 1 failed
asserts: 3 | 2 passed | 1 failed
```
> https://godbolt.org/z/f4jEcv9vo
Motivation
Testing is a very important part of the Software Development, however, C++ doesn't provide any good testing facilities out of the box,
which often leads into a poor testing experience for develops and/or lack of tests/coverage in general.
> One should treat testing code as production code!
Additionally, well established testing practises such as [Test Driven Development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development)/[Behaviour Driven Development (BDD)](https://en.wikipedia.org/wiki/Behavior-driven_development) are often not followed due to the same reasons.
The following snippet is a common example of testing with projects in C++.
```cpp
int main() {
// should sum numbers
{
assert(3 == sum(1, 2));
}
}
```
There are quite a few problems with the approach above
* No names for tests (Hard to follow intentions by further readers)
* No automatic registration of tests (No way to run specific tests)
* Hard to debug (Assertions don't provide any information why it failed)
* Hard to scale (No easy path forward for parameterized tests, multiple suites, parallel execution, etc...)
* Hard to integrate (No easy way to have a custom output such as XML for CI integration)
* Easy to make mistakes (With implicit casting, floating point comparison, pointer comparison for strings, etc...)
* Hard to follow good practises such as `TDD/BDD` (Lack of support for sections and declarative expressions)
* ...
`UT` is trying to address these issues by simplifying testing experience with a few simple steps:
* Just get a single [header/module](https://github.com/boost-ext/ut/blob/master/include/boost/ut.hpp)
* Integrate it into your project
* Learn a few simple concepts ([expect, test, suite](#api))
And you good to go!
Okay, great, but why I would use `UT` over other/similar testing frameworks already available in C++?
* [Boost.Test](https://github.com/boostorg/test)
* [GoogleTest](https://github.com/google/googletest)
* [Catch](https://github.com/catchorg/Catch2)
* [...](https://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C++)
Great question! There are a few unique features which makes `UT` worth trying
* Firstly, it supports all the basic Unit Testing Framework features (automatic registration of tests, assertions, suites, etc...)
* It's easy to integrate (it's just one [header/module](https://github.com/boost-ext/ut/blob/master/include/boost/ut.hpp))
* It's macro free which makes testing experience that much nicer (it uses modern C++ features instead, macros are opt-in rather than being compulsory - [Can I still use macros?](#macros))
* It's flexible (all parts of the framework such as: [runner, reporter, printer](#examples) can be customized, basically most other Unit Testing Frameworks can be implemented on top of UT primitives)
* It has smaller learning curve (just a few simple concepts ([expect, test, suite](#api)))
* It leverages C++ features to support more complex testing ([parameterized](#examples))
* It's faster to compile and execute than similar frameworks which makes it suitable for bigger projects without additional hassle ([Benchmarks](#benchmarks))
* It supports [TDD/BDD](#examples) workflows
* It supports [Gherkin](#examples) specification
* It supports [Spec](#examples)
* ...
Sounds intriguing/interesting? Learn more at
* [Tutorial](#tutorial)
* [Examples](#examples)
* [User-Guide](#user-guide)
Quick Start
> https://bit.ly/ut-quick-start (slides)
Overview
* No dependencies ([C++20](#cpp-20), Tested Compilers: GCC-9+, Clang-9.0+, Apple Clang-11.0.0+, MSVC-2019+*, Clang-cl-9.0+
* Single header/module ([boost/ut.hpp](https://github.com/boost-ext/ut/blob/master/include/boost/ut.hpp))
* Macro-free ([How does it work?](#how-it-works))
* Easy to use ([Minimal API](#api) - `test, suite, operators, literals, [expect]`)
* Fast to compile/execute ([Benchmarks](#benchmarks))
* Features ([Assertions](https://github.com/boost-ext/ut/blob/master/example/expect.cpp), [Suites](https://github.com/boost-ext/ut/blob/master/example/suite.cpp), [Tests](https://github.com/boost-ext/ut/blob/master/example/test.cpp), [Sections](https://github.com/boost-ext/ut/blob/master/example/section.cpp), [Parameterized](https://github.com/boost-ext/ut/blob/master/example/parameterized.cpp), [BDD](https://github.com/boost-ext/ut/blob/master/example/BDD.cpp), [Gherkin](https://github.com/boost-ext/ut/blob/master/example/gherkin.cpp), [Spec](https://github.com/boost-ext/ut/blob/master/example/spec.cpp), [Matchers](https://github.com/boost-ext/ut/blob/master/example/matcher.cpp), [Logging](https://github.com/boost-ext/ut/blob/master/example/log.cpp), [Runners](https://github.com/boost-ext/ut/blob/master/example/cfg/runner.cpp), [Reporters](https://github.com/boost-ext/ut/blob/master/example/cfg/reporter.cpp), [...](https://github.com/boost-ext/ut/blob/master/example))
* Integrations ([ApprovalTests.cpp](https://github.com/approvals/ApprovalTests.cpp/releases/tag/v.7.0.0))
Tutorial
Step 0: Get it...
> Get the latest latest header/module from [here!](https://github.com/boost-ext/ut/blob/master/include/boost/ut.hpp)
> Include/Import
```cpp
// #include // single header
// import boost.ut; // single module (C++20)
int main() { }
```
> Compile & Run
```
$CXX main.cpp && ./a.out
```
```
All tests passed (0 assert in 0 test)
```
> [Optional] Install it
```
cmake -Bbuild -H.
cd build && make # run tests
cd build && make install # install
```
> [Optional] CMake integration
This project provides a CMake config and target.
Just load `ut` with `find_package` to import the `Boost::ut` target.
Linking against this target will add the necessary include directory for the single header file.
This is demonstrated in the following example.
```cmake
find_package(ut REQUIRED)
add_library(my_test my_test.cpp)
target_link_libraries(my_test PRIVATE Boost::ut)
```
> [Optional] [Conan](https://conan.io) integration
The [boost-ext-ut](https://conan.io/center/boost-ext-ut) package is available from [Conan Center](https://conan.io/center/).
Just include it in your project's Conanfile with `boost-ext-ut/2.3.1`.
Step 1: Expect it...
> Let's write our first assertion, shall we?
```cpp
int main() {
boost::ut::expect(true);
}
```
```
All tests passed (1 asserts in 0 test)
```
> https://godbolt.org/z/vfx-eB
> Okay, let's make it fail now?
```cpp
int main() {
boost::ut::expect(1 == 2);
}
```
```
main.cpp:4:FAILED [false]
===============================================================================
tests: 0 | 0 failed
asserts: 1 | 0 passed | 1 failed
```
> https://godbolt.org/z/7qTePx
> Notice that expression `1 == 2` hasn't been printed. Instead we got `false`?
> Let's print it then?
```cpp
int main() {
using namespace boost::ut;
expect(1_i == 2);
}
```
```
main.cpp:4:FAILED [1 == 2]
===============================================================================
tests: 0 | 0 failed
asserts: 1 | 0 passed | 1 failed
```
> https://godbolt.org/z/7MXVzu
> Okay, now we have it! `1 == 2` has been printed as expected.
> Notice the User Defined Literal (UDL) `1_i` was used.
> `_i` is a compile-time constant integer value
* It allows to override comparison operators ð
* It disallow comparison of different types ð
See the [User-guide](#user-guide) for more details.
> Alternatively, a `terse` notation (no expect required) can be used.
```cpp
int main() {
using namespace boost::ut::literals;
using namespace boost::ut::operators::terse;
1_i == 2; // terse notation
}
```
```
main.cpp:7:FAILED [1 == 2]
===============================================================================
tests: 0 | 0 failed
asserts: 1 | 0 passed | 1 failed
```
> https://godbolt.org/z/s77GSm
> Other expression syntaxes are also available.
```cpp
expect(1_i == 2); // UDL syntax
expect(1 == 2_i); // UDL syntax
expect(that % 1 == 2); // Matcher syntax
expect(eq(1, 2)); // eq/neq/gt/ge/lt/le
```
```
main.cpp:6:FAILED [1 == 2]
main.cpp:7:FAILED [1 == 2]
main.cpp:8:FAILED [1 == 2]
main.cpp:9:FAILED [1 == 2]
===============================================================================
tests: 0 | 0 failed
asserts: 4 | 0 passed | 4 failed
```
> https://godbolt.org/z/QbgGtc
> Okay, but what about the case if my assertion is fatal.
> Meaning that the program will crash unless the processing will be terminated.
> Nothing easier, let's just add `fatal` call to make the test fail immediately.
```cpp
expect(fatal(1 == 2_i)); // fatal assertion
expect(1_i == 2); // not executed
```
```
main.cpp:6:FAILED [1 == 2]
===============================================================================
tests: 1 | 1 failed
asserts: 2 | 0 passed | 2 failed
```
> https://godbolt.org/z/WMe8Y1
> But my expression is more complex than just simple comparisons.
> Not a problem, logic operators are also supported in the `expect` ð.
```cpp
expect(42l == 42_l and 1 == 2_i); // compound expression
```
```
main.cpp:5:FAILED [(42 == 42 and 1 == 2)]
===============================================================================
tests: 0 | 0 failed
asserts: 1 | 0 passed | 1 failed
```
> https://godbolt.org/z/aEhX4t
> Can I add a custom message though?
> Sure, `expect` calls are streamable!
```cpp
int main() {
expect(42l == 42_l and 1 == 2_i) << "additional info";
}
```
```
main.cpp:5:FAILED [(42 == 42 and 1 == 2)] additional info
===============================================================================
tests: 0 | 0 failed
asserts: 1 | 0 passed | 1 failed
```
> That's nice, can I use custom messages and fatal assertions?
> Yes, stream the `fatal`!
```cpp
expect(fatal(1 == 2_i)) << "fatal assertion";
expect(1_i == 2);
```
```
FAILED
in: main.cpp:6 - test condition: [1 == 2]
fatal assertion
===============================================================================
tests: 0 | 2 failed
asserts: 0 | 0 passed | 2 failed
```
> I use `std::expected`, can I stream its `error()` upon failure?
> Yes, since `std::expected`'s `error()` can only be called when there is no
> value it requires lazy evaluation.
```cpp
"lazy log"_test = [] {
std::expected e = std::unexpected("lazy evaluated");
expect(e.has_value()) << [&] { return e.error(); } << fatal;
expect(e.value() == true);
};
```
```
Running test "lazy log"... FAILED
in: main.cpp:12 - test condition: [false]
lazy evaluated
===============================================================================
tests: 1 | 2 failed
asserts: 0 | 0 passed | 2 failed
```
> https://godbolt.org/z/v2PDuU
Step 2: Group it...
> Assertions are great, but how to combine them into more cohesive units?
> `Test cases` are the way to go! They allow to group expectations for the same functionality into coherent units.
```cpp
"hello world"_test = [] { };
```
> Alternatively `test("hello world") = [] {}` can be used.
```
All tests passed (0 asserts in 1 tests)
```
> https://godbolt.org/z/Bh-EmY
> Notice `1 tests` but `0 asserts`.
> Let's make our first end-2-end test case, shall we?
```cpp
int main() {
"hello world"_test = [] {
int i = 43;
expect(42_i == i);
};
}
```
```
Running "hello world"...
main.cpp:8:FAILED [42 == 43]
FAILED
===============================================================================
tests: 1 | 1 failed
asserts: 1 | 0 passed | 1 failed
```
> https://godbolt.org/z/Y43mXz
> ð We are done here!
> I'd like to nest my tests, though and share setup/tear-down.
> With lambdas used to represents `tests/sections` we can easily achieve that.
> Let's just take a look at the following example.
```cpp
int main() {
"[vector]"_test = [] {
std::vector v(5);
expect(fatal(5_ul == std::size(v)));
should("resize bigger") = [v] { // or "resize bigger"_test
mut(v).resize(10);
expect(10_ul == std::size(v));
};
expect(fatal(5_ul == std::size(v)));
should("resize smaller") = [=]() mutable { // or "resize smaller"_test
v.resize(0);
expect(0_ul == std::size(v));
};
}
}
```
```
All tests passed (4 asserts in 1 tests)
```
> https://godbolt.org/z/XWAdYt
> Nice! That was easy, but I'm a believer into Behaviour Driven Development (`BDD`).
> Is there a support for that?
> Yes! Same example as above just with the `BDD` syntax.
```cpp
int main() {
"vector"_test = [] {
given("I have a vector") = [] {
std::vector v(5);
expect(fatal(5_ul == std::size(v)));
when("I resize bigger") = [=] {
mut(v).resize(10);
then("The size should increase") = [=] {
expect(10_ul == std::size(v));
};
};
};
};
}
```
```
All tests passed (2 asserts in 1 tests)
```
> https://godbolt.org/z/dnvxsE
> On top of that, `feature/scenario` aliases can be leveraged.
```cpp
int main() {
feature("vector") = [] {
scenario("size") = [] {
given("I have a vector") = [] {
std::vector v(5);
expect(fatal(5_ul == std::size(v)));
when("I resize bigger") = [=] {
mut(v).resize(10);
then("The size should increase") = [=] {
expect(10_ul == std::size(v));
};
};
};
};
};
}
```
```
All tests passed (2 asserts in 1 tests)
```
> https://godbolt.org/z/T4cWss
> Can I use `Gherkin`?
> Yeah, let's rewrite the example using `Gherkin` specification
```cpp
int main() {
bdd::gherkin::steps steps = [](auto& steps) {
steps.feature("Vector") = [&] {
steps.scenario("*") = [&] {
steps.given("I have a vector") = [&] {
std::vector v(5);
expect(fatal(5_ul == std::size(v)));
steps.when("I resize bigger") = [&] {
v.resize(10);
};
steps.then("The size should increase") = [&] {
expect(10_ul == std::size(v));
};
};
};
};
};
"Vector"_test = steps |
R"(
Feature: Vector
Scenario: Resize
Given I have a vector
When I resize bigger
Then The size should increase
)";
}
```
```
All tests passed (2 asserts in 1 tests)
```
> https://godbolt.org/z/jb1d8P
> Nice, is `Spec` notation supported as well?
```cpp
int main() {
describe("vector") = [] {
std::vector v(5);
expect(fatal(5_ul == std::size(v)));
it("should resize bigger") = [v] {
mut(v).resize(10);
expect(10_ul == std::size(v));
};
};
}
```
```
All tests passed (2 asserts in 1 tests)
```
> https://godbolt.org/z/6jKKzT
> That's great, but how can call the same tests with different arguments/types to be DRY (Don't Repeat Yourself)?
> Parameterized tests to the rescue!
```cpp
int main() {
for (auto i : std::vector{1, 2, 3}) {
test("parameterized " + std::to_string(i)) = [i] { // 3 tests
expect(that % i > 0); // 3 asserts
};
}
}
```
```
All tests passed (3 asserts in 3 tests)
```
> https://godbolt.org/z/Utnd6X
> That's it ðŪ!
> Alternatively, a convenient test syntax is also provided ð
```cpp
int main() {
"args"_test = [](const auto& arg) {
expect(arg > 0_i) << "all values greater than 0";
} | std::vector{1, 2, 3};
}
```
```
All tests passed (3 asserts in 3 tests)
```
> https://godbolt.org/z/6FHtpq
> Check [Examples](#examples) for further reading.
Step 3: Scale it...
> Okay, but my project is more complex than that. How can I scale?
> `Test suites` will make that possible. By using `suite` in translation units
> `tests` defined inside will be automatically registered ð
```cpp
suite errors = [] { // or suite<"nameofsuite">
"exception"_test = [] {
expect(throws([] { throw 0; })) << "throws any exception";
};
"failure"_test = [] {
expect(aborts([] { assert(false); }));
};
};
int main() { }
```
```
All tests passed (2 asserts in 2 tests)
```
> https://godbolt.org/z/_ccGwZ
---
> What's next?
> * [Examples](#examples)
> * [User-Guide](#user-guide)
Examples
Assertions
```cpp
// operators
expect(0_i == sum());
expect(2_i != sum(1, 2));
expect(sum(1) >= 0_i);
expect(sum(1) <= 1_i);
```
```cpp
// message
expect(3_i == sum(1, 2)) << "wrong sum";
```
```cpp
// expressions
expect(0_i == sum() and 42_i == sum(40, 2));
expect(0_i == sum() or 1_i == sum()) << "compound";
```
```cpp
// matchers
expect(that % 0 == sum());
expect(that % 42 == sum(40, 2) and that % (1 + 2) == sum(1, 2));
expect(that % 1 != 2 or 2_i > 3);
```
```cpp
// eq/neq/gt/ge/lt/le
expect(eq(42, sum(40, 2)));
expect(neq(1, 2));
expect(eq(sum(1), 1) and neq(sum(1, 2), 2));
expect(eq(1, 1) and that % 1 == 1 and 1_i == 1);
```
```cpp
// floating points
expect(42.1_d == 42.101) << "epsilon=0.1";
expect(42.10_d == 42.101) << "epsilon=0.01";
expect(42.10000001 == 42.1_d) << "epsilon=0.1";
```
```cpp
// constant
constexpr auto compile_time_v = 42;
auto run_time_v = 99;
expect(constant<42_i == compile_time_v> and run_time_v == 99_i);
```
```cpp
// failure
expect(1_i == 2) << "should fail";
expect(sum() == 1_i or 2_i == sum()) << "sum?";
```
```
assertions.cpp:53:FAILED [1 == 2] should fail
assertions.cpp:54:FAILED [(0 == 1 or 2 == 0)] sum?
===============================================================================
tests: 0 | 0 failed
asserts: 20 | 18 passed | 2 failed
```
> https://godbolt.org/z/E1c7G5
Tests
Run/Skip/Tag
```cpp
"run UDL"_test = [] {
expect(42_i == 42);
};
skip / "don't run UDL"_test = [] {
expect(42_i == 43) << "should not fire!";
};
```
```
All tests passed (1 asserts in 1 tests)
1 tests skipped
```
```cpp
test("run function") = [] {
expect(42_i == 42);
};
skip / test("don't run function") = [] {
expect(42_i == 43) << "should not fire!";
};
```
```
All tests passed (1 asserts in 1 tests)
1 tests skipped
```
```cpp
tag("nightly") / tag("slow") /
"performance"_test= [] {
expect(42_i == 42);
};
tag("slow") /
"run slowly"_test= [] {
expect(42_i == 43) << "should not fire!";
};
```
```
cfg = {.tag = {"nightly"}};
```
```
All tests passed (1 asserts in 1 tests)
1 tests skipped
```
> https://godbolt.org/z/X3_kG4
Sections
```cpp
"[vector]"_test = [] {
std::vector v(5);
expect(fatal(5_ul == std::size(v)));
should("resize bigger") = [=] { // or "resize bigger"_test
mut(v).resize(10);
expect(10_ul == std::size(v));
};
expect(fatal(5_ul == std::size(v)));
should("resize smaller") = [=]() mutable { // or "resize smaller"_test
v.resize(0);
expect(0_ul == std::size(v));
};
};
```
```
All tests passed (4 asserts in 1 tests)
```
> https://godbolt.org/z/cE91bj
Behavior Driven Development (BDD)
```cpp
"Scenario"_test = [] {
given("I have...") = [] {
when("I run...") = [] {
then("I expect...") = [] { expect(1_i == 1); };
then("I expect...") = [] { expect(1 == 1_i); };
};
};
};
```
```
All tests passed (2 asserts in 1 tests)
```
> https://godbolt.org/z/mNBySr
Gherkin
```cpp
int main() {
bdd::gherkin::steps steps = [](auto& steps) {
steps.feature("*") = [&] {
steps.scenario("*") = [&] {
steps.given("I have a number {value}") = [&](int value) {
auto number = value;
steps.when("I add {value} to it") = [&](int value) {
number += value;
};
steps.then("I expect number to be {value}") = [&](int value) {
expect(that % number == value);
};
};
};
};
};
"Gherkin"_test = steps |
R"(
Feature: Number
Scenario: Addition
Given I have a number 40
When I add 2 to it
Then I expect number to be 42
)";
}
```
```
All tests passed (1 asserts in 1 tests)
```
> https://godbolt.org/z/BP3hyt
Spec
```cpp
int main() {
describe("equality") = [] {
it("should be equal") = [] { expect(0_i == 0); };
it("should not be equal") = [] { expect(1_i != 0); };
};
}
```
```
All tests passed (2 asserts in 1 tests)
```
> https://godbolt.org/z/BXYJ3a
Parameterized
```cpp
for (auto i : std::vector{1, 2, 3}) {
test("parameterized " + std::to_string(i)) = [i] {
expect(that % i > 0);
};
}
"args"_test =
[](auto arg) {
expect(arg >= 1_i);
}
| std::vector{1, 2, 3};
"types"_test =
[] {
expect(std::is_integral_v) << "all types are integrals";
}
| std::tuple{};
"args and types"_test =
[](TArg arg) {
expect(fatal(std::is_integral_v));
expect(42_i == arg or "is true"_b == arg);
expect(type == type or type == type);
}
| std::tuple{true, 42};
```
When using the `operator|` syntax instead of a `for` loop, the test name will automatically
be extended to avoid duplicate names. For example, the test name for the `args and types` test
will be `args and types (true, bool)` for the first parameter and `args and types (42, int)`
for the second parameter. For simple built-in types (integral types and floating point numbers),
the test name will contain the parameter values. For other types, the parameters will simply be
enumerated. For example, if we would extend the test above to use
`std::tuple{true, 42, std::complex{0.5, 1}}`, the test name in the third run would be
`args and types (3rd parameter, std::complex)`. If you want to have the actual value of
a non-integral type included in the test name, you can overload the `format_test_parameter` function.
See the [example on parameterized tests](https://github.com/boost-ext/ut/blob/master/example/parameterized.cpp)
for details.
```
All tests passed (14 asserts in 10 tests)
```
> https://godbolt.org/z/4xGGdo
> And whenever I need to know the specific type for which the test failed,
> I can use `reflection::type_name()`, like this:
```cpp
"types with type name"_test =
[]() {
expect(std::is_unsigned_v) << reflection::type_name() << "is unsigned";
}
| std::tuple{};
```
```
Running "types with type name"...PASSED
Running "types with type name"...
:10:FAILED [false] float is unsigned
FAILED
```
> https://godbolt.org/z/MEnGnbTY4
Suites
```cpp
namespace ut = boost::ut;
ut::suite errors = [] {
using namespace ut;
"throws"_test = [] {
expect(throws([] { throw 0; }));
};
"doesn't throw"_test = [] {
expect(nothrow([]{}));
};
};
int main() { }
```
```
All tests passed (2 asserts in 2 tests)
```
> https://godbolt.org/z/CFbTP9
Misc
Logging using streams
```cpp
"logging"_test = [] {
log << "pre";
expect(42_i == 43) << "message on failure";
log << "post";
};
```
```
Running "logging"...
pre
logging.cpp:8:FAILED [42 == 43] message on failure
post
FAILED
===============================================================================
tests: 1 | 1 failed
asserts: 1 | 0 passed | 1 failed
```
> https://godbolt.org/z/26fPSY
Logging using formatting
This requires using C++20 with a standard library with std::format support.
```cpp
"logging"_test = [] {
log("\npre {} == {}\n", 42, 43);
expect(42_i == 43) << "message on failure";
log("\npost {} == {} -> {}\n", 42, 43, 42 == 43);
};
```
```
Running "logging"...
pre 42 == 43
logging.cpp:8:FAILED [42 == 43] message on failure
post 42 == 43 -> false
FAILED
===============================================================================
tests: 1 | 1 failed
asserts: 1 | 0 passed | 1 failed
```
> https://godbolt.org/z/26fPSY
Matchers
```cpp
"matchers"_test = [] {
constexpr auto is_between = [](auto lhs, auto rhs) {
return [=](auto value) {
return that % value >= lhs and that % value <= rhs;
};
};
expect(is_between(1, 100)(42));
expect(not is_between(1, 100)(0));
};
```
```
All tests passed (2 asserts in 1 tests)
```
> https://godbolt.org/z/4qwrCi
Exceptions/Aborts
```cpp
"exceptions/aborts"_test = [] {
expect(throws([] { throw std::runtime_error{""}; }))
<< "throws runtime_error";
expect(throws([] { throw 0; })) << "throws any exception";
expect(nothrow([]{})) << "doesn't throw";
expect(aborts([] { assert(false); }));
};
```
```
All tests passed (4 asserts in 1 tests)
```
> https://godbolt.org/z/A2EehK
Config
Runner
```cpp
namespace ut = boost::ut;
namespace cfg {
class runner {
public:
template auto on(ut::events::test test) { test(); }
template auto on(ut::events::skip) {}
template
auto on(ut::events::assertion) -> bool { return true; }
auto on(ut::events::fatal_assertion) {}
template auto on(ut::events::log) {}
};
} // namespace cfg
template<> auto ut::cfg = cfg::runner{};
```
> https://godbolt.org/z/jdg687
Reporter
```cpp
namespace ut = boost::ut;
namespace cfg {
class reporter {
public:
auto on(ut::events::test_begin) -> void {}
auto on(ut::events::test_run) -> void {}
auto on(ut::events::test_skip) -> void {}
auto on(ut::events::test_end) -> void {}
template auto on(ut::events::log) -> void {}
template
auto on(ut::events::assertion_pass) -> void {}
template
auto on(ut::events::assertion_fail) -> void {}
auto on(ut::events::fatal_assertion) -> void {}
auto on(ut::events::exception) -> void {}
auto on(ut::events::summary) -> void {}
};
} // namespace cfg
template <>
auto ut::cfg = ut::runner{};
```
> https://godbolt.org/z/gsAPKg
Printer
```cpp
namespace ut = boost::ut;
namespace cfg {
struct printer : ut::printer {
template
auto& operator<<(T&& t) {
std::cerr << std::forward(t);
return *this;
}
};
} // namespace cfg
template <>
auto ut::cfg = ut::runner>{};
int main() {
using namespace ut;
"printer"_test = [] {};
}
```
> https://godbolt.org/z/XCscF9
User Guide
API
```cpp
export module boost.ut; /// __cpp_modules
namespace boost::inline ext::ut::inline v2_3_1 {
/**
* Represents test suite object
*/
struct suite final {
/**
* Creates and executes test suite
* @example suite _ = [] {};
* @param suite test suite function
*/
constexpr explicit(false) suite(auto suite);
};
/**
* Creates a test
* @example "name"_test = [] {};
* @return test object to be executed
*/
constexpr auto operator""_test;
/**
* Creates a test
* @example test("name") = [] {};
* @return test object to be executed
*/
constexpr auto test = [](const auto name);
/**
* Creates a test
* @example should("name") = [] {};
* @return test object to be executed
*/
constexpr auto should = [](const auto name);
/**
* Behaviour Driven Development (BDD) helper functions
* @param name step name
* @return test object to be executed
*/
constexpr auto given = [](const auto name);
constexpr auto when = [](const auto name);
constexpr auto then = [](const auto name);
/**
* Evaluates an expression
* @example expect(42 == 42_i and 1 != 2_i);
* @param expr expression to be evaluated
* @param source location https://en.cppreference.com/w/cpp/utility/source_location
* @return stream
*/
constexpr OStream& expect(
Expression expr,
const std::source_location& location = std::source_location::current()
);
struct {
/**
* @example (that % 42 == 42);
* @param expr expression to be evaluated
*/
[[nodiscard]] constexpr auto operator%(Expression expr) const;
} that{};
inline namespace literals {
/**
* User defined literals to represent constant values
* @example 42_i, 0_uc, 1.23_d
*/
constexpr auto operator""_i; /// int
constexpr auto operator""_s; /// short
constexpr auto operator""_c; /// char
constexpr auto operator""_l; /// long
constexpr auto operator""_ll; /// long long
constexpr auto operator""_u; /// unsigned
constexpr auto operator""_uc; /// unsigned char
constexpr auto operator""_us; /// unsigned short
constexpr auto operator""_ul; /// unsigned long
constexpr auto operator""_f; /// float
constexpr auto operator""_d; /// double
constexpr auto operator""_ld; /// long double
/**
* Represents dynamic values
* @example _i(42), _f(42.)
*/
constexpr auto _b(bool);
constexpr auto _c(char);
constexpr auto _s(short);
constexpr auto _i(int);
constexpr auto _l(long);
constexpr auto _ll(long long);
constexpr auto _u(unsigned);
constexpr auto _uc(unsigned char);
constexpr auto _us(unsigned short);
constexpr auto _ul(unsigned long);
constexpr auto _f(float);
constexpr auto _d(double);
constexpr auto _ld(long double);
/**
* Logical representation of constant boolean (true) value
* @example "is set"_b : true
* not "is set"_b : false
*/
constexpr auto operator ""_b;
} // namespace literals
inline namespace operators {
/**
* Comparison functions to be used in expressions
* @example eq(42, 42), neq(1, 2)
*/
constexpr auto eq(Operator lhs, Operator rhs); /// ==
constexpr auto neq(Operator lhs, Operator rhs); /// !=
constexpr auto gt(Operator lhs, Operator rhs); /// >
constexpr auto ge(Operator lhs, Operator rhs); /// >=
constexpr auto lt(Operator lhs, Operator rhs); /// <
constexpr auto le(Operator lhs, Operator rhs); /// <=
/**
* Overloaded comparison operators to be used in expressions
* @example (42_i != 0)
*/
constexpr auto operator==;
constexpr auto operator!=;
constexpr auto operator>;
constexpr auto operator>=;
constexpr auto operator<;
constexpr auto operator<=;
/**
* Overloaded logic operators to be used in expressions
* @example (42_i != 0 and 1 == 2_i)
*/
constexpr auto operator and;
constexpr auto operator or;
constexpr auto operator not;
/**
* Executes parameterized tests
* @example "parameterized"_test = [](auto arg) {} | std::tuple{1, 2, 3};
*/
constexpr auto operator|;
/**
* Creates tags
* @example tag("slow") / tag("nightly") / "perf"_test = []{};
*/
constexpr auto operator/;
/**
* Creates a `fatal_assertion` from an expression
* @example (42_i == 0) >> fatal
*/
constexpr auto operator>>;
} // namespace operators
/**
* Creates skippable test object
* @example skip / "don't run"_test = [] { };
*/
constexpr auto skip = tag("skip");
struct {
/**
* @example log << "message!";
* @param msg stringable message
*/
auto& operator<<(Msg msg);
} log{};
/**
* Makes object mutable
* @example mut(object)
* @param t object to be mutated
*/
template auto mut(const T& t) -> T&;
/**
* Default execution flow policy
*/
class runner {
public:
/**
* @example cfg = {
.filter = "test.section.*",
.colors = { .none = "" },
.dry__run = true
};
* @param options.filter {default: "*"} runs all tests which names
matches test.section.* filter
* @param options.colors {default: {
.none = "\033[0m",
.pass = "\033[32m",
.fail = "\033[31m"
} if specified then overrides default color values
* @param options.dry_run {default: false} if true then print test names to be
executed without running them
*/
auto operator=(options);
/**
* @example suite _ = [] {};
* @param suite() executes suite
*/
template
auto on(ut::events::suite);
/**
* @example "name"_test = [] {};
* @param test.type ["test", "given", "when", "then"]
* @param test.name "name"
* @param test.arg parameterized argument
* @param test() executes test
*/
template
auto on(ut::events::test);
/**
* @example skip / "don't run"_test = []{};
* @param skip.type ["test", "given", "when", "then"]
* @param skip.name "don't run"
* @param skip.arg parameterized argument
*/
template
auto on(ut::events::skip);
/**
* @example file.cpp:42: expect(42_i == 42);
* @param assertion.expr 42_i == 42
* @param assertion.location { "file.cpp", 42 }
* @return true if expr passes, false otherwise
*/
template
auto on(ut::events::assertion) -> bool;
/**
* @example expect((2_i == 1) >> fatal)
* @note triggered by `fatal`
* should std::exit
*/
auto on(ut::events::fatal_assertion);
/**
* @example log << "message"
* @param log.msg "message"
*/
template
auto on(ut::events::log);
/**
* Explicitly runs registered test suites
* If not called directly test suites are executed with run's destructor
* @example return run({.report_errors = true})
* @param run_cfg.report_errors {default: false} if true it prints the summary after running
*/
auto run(run_cfg);
/**
* Runs registered test suites if they haven't been explicitly executed already
*/
~run();
};
/**
* Default reporter policy
*/
class reporter {
public:
/**
* @example file.cpp:42: "name"_test = [] {};
* @param test_begin.type ["test", "given", "when", "then"]
* @param test_begin.name "name"
* @param test_begin.location { "file.cpp", 42 }
*/
auto on(ut::events::test_begin) -> void;
/**
* @example "name"_test = [] {};
* @param test_run.type ["test", "given", "when", "then"]
* @param test_run.name "name"
*/
auto on(ut::events::test_run) -> void;
/**
* @example "name"_test = [] {};
* @param test_skip.type ["test", "given", "when", "then"]
* @param test_skip.name "name"
*/
auto on(ut::events::test_skip) -> void;
/**
* @example "name"_test = [] {};
* @param test_end.type ["test", "given", "when", "then"]
* @param test_end.name "name"
*/
auto on(ut::events::test_end) -> void;
/**
* @example log << "message"
* @param log.msg "message"
*/
template
auto on(ut::events::log) -> void;
/**
* @example file.cpp:42: expect(42_i == 42);
* @param assertion_pass.expr 42_i == 42
* @param assertion_pass.location { "file.cpp", 42 }
*/
template
auto on(ut::events::assertion_pass) -> void;
/**
* @example file.cpp:42: expect(42_i != 42);
* @param assertion_fail.expr 42_i != 42
* @param assertion_fail.location { "file.cpp", 42 }
*/
template
auto on(ut::events::assertion_fail) -> void;
/**
* @example expect((2_i == 1) >> fatal)
* @note triggered by `fatal`
* should std::exit
*/
auto on(ut::events::fatal_assertion) -> void;
/**
* @example "exception"_test = [] { throw std::runtime_error{""}; };
*/
auto on(ut::events::exception) -> void;
/**
* @note triggered on destruction of runner
*/
auto on(ut::events::summary) -> void;
};
/**
* Used to override default running policy
* @example template <> auto cfg = runner{};
*/
struct override {};
/**
* Default UT execution policy
* Can be overwritten with override
*/
template auto cfg = runner{};
}
```
Configuration
| Option | Description | Example |
|-|-|-|
| `BOOST_UT_VERSION` | Current version | `2'3'1` |
FAQ
How does it work?
> `suite`
```cpp
/**
* Represents suite object
* @example suite _ = []{};
*/
struct suite final {
/**
* Assigns and executes test suite
*/
[[nodiscard]] constexpr explicit(false) suite(Suite suite) {
suite();
}
};
```
> `test`
```cpp
/**
* Creates named test object
* @example "hello world"_test
* @return test object
*/
[[nodiscard]] constexpr Test operator ""_test(const char* name, std::size_t size) {
return test{{name, size}};
}
```
```cpp
/**
* Represents test object
*/
struct test final {
std::string_view name{}; /// test case name
/**
* Assigns and executes test function
* @param test function
*/
constexpr auto operator=(const Test& test) {
std::cout << "Running... " << name << '\n';
test();
}
};
```
> `expect`
```cpp
/**
* Evaluates an expression
* @example expect(42_i == 42);
* @param expr expression to be evaluated
* @param source location https://en.cppreference.com/w/cpp/utility/source_location
* @return stream
*/
constexpr OStream& expect(
Expression expr,
const std::source_location& location = std::source_location::current()
) {
if (not static_cast(expr) {
std::cerr << location.file()
<< ':'
<< location.line()
<< ":FAILED: "
<< expr
<< '\n';
}
return std::cerr;
}
```
```cpp
/**
* Creates constant object for which operators can be overloaded
* @example 42_i
* @return integral constant object
*/
template
[[nodiscard]] constexpr Operator operator""_i() -> integral_constant>;
```
```cpp
/**
* Overloads comparison if at least one of {lhs, rhs} is an Operator
* @example (42_i == 42)
* @param lhs Left-hand side operator
* @param rhs Right-hand side operator
* @return Comparison object
*/
[[nodiscard]] constexpr auto operator==(Operator lhs, Operator rhs) {
return eq{lhs, rhs};
}
```
```cpp
/**
* Comparison Operator
*/
template
struct eq final {
TLhs lhs{}; // Left-hand side operator
TRhs rhs{}; // Right-hand side operator
/**
* Performs comparison operation
* @return true if expression is successful
*/
[[nodiscard]] constexpr explicit operator bool() const {
return lhs == rhs;
}
/**
* Nicely prints the operation
*/
friend auto operator<<(OStream& os, const eq& op) -> Ostream& {
return (os << op.lhs << " == " << op.rhs);
}
};
```
> `Sections`
```cpp
/**
* Convenient aliases for creating test named object
* @example should("return true") = [] {};
*/
constexpr auto should = [](const auto name) { return test{name}; };
```
> `Behaviour Driven Development (BDD)`
```cpp
/**
* Convenient aliases for creating BDD tests
* @example feature("Feature") = [] {};
* @example scenario("Scenario") = [] {};
* @example given("I have an object") = [] {};
* @example when("I call it") = [] {};
* @example then("I should get") = [] {};
*/
constexpr auto feature = [](const auto name) { return test{name}; };
constexpr auto scenario = [](const auto name) { return test{name}; };
constexpr auto given = [](const auto name) { return test{name}; };
constexpr auto when = [](const auto name) { return test{name}; };
constexpr auto then = [](const auto name) { return test{name}; };
```
> https://godbolt.org/z/6Nk5Mi
> `Spec`
```cpp
/**
* Convenient aliases for creating Spec tests
* @example describe("test") = [] {};
* @example it("should...") = [] {};
*/
constexpr auto describe = [](const auto name) { return test{name}; };
constexpr auto it = [](const auto name) { return test{name}; };
```
> [Example implementation](https://github.com/boost-ext/ut/tree/gh-pages/denver-cpp-2020/example)
> Try it online
* Header - https://godbolt.org/z/x96n8b
* Module - https://wandbox.org/permlink/LrV7WwIgghTP1nrs
Fast compilation times (Benchmarks) ?
> Implementation
* Leveraging [C++20](#cpp-20) features
* Avoiding unique types for lambda expressions
```cpp
template
requires not std::convertible_to>
constexpr auto operator=(Test test);
vs
// Compiles 5x faster because it doesn't introduce a new type for each lambda
constexpr auto operator=(void (*test)());
```
* `Type-name` erasure (allows types/function memoization)
```cpp
eq, int>{ {}, 42 }
vs
// Can be memoized - faster to compile
eq{42, 42}
```
* Limiting preprocessor work
* Single header/module
* Minimal number of include files
* Simplified versions of
* `std::function`
* `std::string_view`
C++20 features?
* API
* [Source Location](https://eel.is/c++draft/support.srcloc#source.location.syn)
* Assertions - `expect(false)` - ` __FILE__:__LINE__:FAILED [false]`
* [Designated initializers](https://eel.is/c++draft/dcl.init#nt:designated-initializer-list)
* Configuration - `cfg = {.filter = "test"}`
* [Non-Type Template Parameter](https://eel.is/c++draft/temp.arg.nontype)
* Constant matchers - `constant<42_i == 42>`
* [Template Parameter List for generic lambdas](https://eel.is/c++draft/expr.prim.lambda)
* Parameterized tests - `"types"_test = []() {};`
* [Concepts](https://eel.is/c++draft/concepts.lang)
* Operators - `Operator @ Operator`
* [Modules](https://eel.is/c++draft/module)
* `import boost.ut;`
C++2X integration?
> Parameterized tests with Expansion statements (https://wg21.link/P1306r1)
```cpp
template for (auto arg : std::tuple{}) {
test("types " + std::to_string(arg)) = [arg] {
expect(type(arg) == type or type(arg) == type);
};
}
```
```
All tests passed (2 asserts in 2 tests)
```
> https://cppx.godbolt.org/z/dMmqmM
Is standardization an option?
> Personally, I believe that C++ standard could benefit from common testing primitives (`expect`, `""_test`) because
* It lowers the entry-level to the language (no need for third-party libraries)
* It improves the education aspect (one standard way of doing it)
* It makes the language more coherent/stable (consistent design with other features, stable API)
* It makes the testing a first class citizen (shows that the community cares about this aspect of the language)
* It allows to publish tests for the Standard Library (STL) in the standard way (coherency, easier to extend)
* It allows to act as additional documentation as a way to verify whether a particular implementation is conforming (quality, self-verification)
* It helps with establishing standard vocabulary for testing (common across STL and other projects)
Can I still use macros?
> Sure, although please notice that there are negatives of using macros such as
* Error messages might be not clear and/or point to the wrong line
* Global scope will be polluted
* Type safety will be ignored
```cpp
#define EXPECT(...) ::boost::ut::expect(::boost::ut::that % __VA_ARGS__)
#define SUITE ::boost::ut::suite _ = []
#define TEST(name) ::boost::ut::detail::test{"test", name} = [=]() mutable
SUITE {
TEST("suite") {
EXPECT(42 == 42);
};
};
int main() {
TEST("macro") {
EXPECT(1 != 2);
};
TEST("vector") {
std::vector v(5);
EXPECT(fatal(5u == std::size(v))) << "fatal";
TEST("resize bigger") {
v.resize(10);
EXPECT(10u == std::size(v));
};
};
}
```
```
All tests passed (4 asserts in 3 tests)
```
> https://godbolt.org/z/WcEKTr
What about Mocks/Stubs/Fakes?
> Consider using one of the following frameworks
* https://github.com/cpp-testing/GUnit/blob/master/docs/GMock.md
* https://github.com/eranpeer/FakeIt
* https://github.com/dascandy/hippomocks
What about Microbenchmarking?
> [Example benchmark](example/benchmark.cpp)
> Consider using one of the following frameworks
* https://github.com/google/benchmark
* https://github.com/DigitalInBlue/Celero
* https://github.com/libnonius/nonius
* https://github.com/martinus/nanobench
Related materials/talks?
* [[Boost].UT - Unit Testing Framework - Kris Jusiak](https://boost-ext.github.io/ut/denver-cpp-2019)
* [Future of Testing with C++20 - Kris Jusiak](https://boost-ext.github.io/ut/meeting-cpp-2020)
* [Macro-Free Testing with C++20 - Kris Jusiak](https://www.youtube.com/watch?v=irdgFyxOs_Y)
* ["If you liked it then you `"should have put a"_test` on it", Beyonce rule - Kris Jusiak](https://www.youtube.com/watch?v=yCI8MjvOMeE)
* [Principles of Unit Testing With C++ - Dave Steffen and Kris Jusiak](https://www.youtube.com/watch?v=oOcuJdJJ33g)
* [Empirical Unit Testing - Dave Steffen](https://www.twitch.tv/videos/686512433)
How to contribute?
> [CONTRIBUTING](.github/CONTRIBUTING.md)
Benchmarks
| Framework | Version | Standard | License | Linkage | Test configuration |
|-|-|-|-|-|-|
| [Boost.Test](https://github.com/boostorg/test) | [1.71.0](https://www.boost.org/users/history/version_1_71_0.html) | C++03 | Boost 1.0 | single header/library | `static library` |
| [GoogleTest](https://github.com/google/googletest) | [1.10.0](https://github.com/google/googletest/releases/tag/release-1.10.0) | C++11 | BSD-3 | library | `static library` |
| [Catch](https://github.com/catchorg/Catch2) | [2.10.2](https://github.com/catchorg/Catch2/releases/download/v2.10.2/catch.hpp) | C++11 | Boost 1.0 | single header | `CATCH_CONFIG_FAST_COMPILE` |
| [Doctest](https://github.com/onqtam/doctest) | [2.3.5](https://github.com/onqtam/doctest/blob/master/doctest/doctest.h) | C++11 | MIT | single header | `DOCTEST_CONFIG_SUPER_FAST_ASSERTS` |
| [UT](https://github.com/boost-ext/ut) | [1.1.0](https://github.com/boost-ext/ut/blob/master/include/boost/ut.hpp) | C++20 | Boost 1.0 | single header/module | |
Include / 0 tests, 0 asserts, 1 cpp file
Assert / 1 test, 1'000'000 asserts, 1 cpp file
Test / 1'000 tests, 0 asserts, 1 cpp file
Suite / 10'000 tests, 0 asserts, 100 cpp files
Suite+Assert / 10'000 tests, 40'000 asserts, 100 cpp files
Suite+Assert+STL / 10'000 tests, 20'000 asserts, 100 cpp files
Incremental Build - Suite+Assert+STL / 1 cpp file change (1'000 tests, 20'000 asserts, 100 cpp files)
Suite+Assert+STL / 10'000 tests, 20'000 asserts, 100 cpp files (Headers vs Precompiled headers vs C++20 Modules)
> https://github.com/cpp-testing/ut-benchmark
---
**Disclaimer** `UT` is not an official Boost library.
boost-ext-ut-2.3.1/benchmark/ 0000775 0000000 0000000 00000000000 14773232535 0016034 5 ustar 00root root 0000000 0000000 boost-ext-ut-2.3.1/benchmark/CMakeLists.txt 0000664 0000000 0000000 00000001244 14773232535 0020575 0 ustar 00root root 0000000 0000000 #
# Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
function(benchmark name file)
add_executable(b${name} ${file}.cpp)
target_compile_options(b${name} PRIVATE ${ARGN})
target_link_libraries(b${name} PRIVATE Boost::ut)
ut_add_custom_command_or_test(TARGET b${name} COMMAND b${name})
endfunction()
benchmark(expect_udl expect "-DEXPECT_UDL")
benchmark(expect_that expect "-DEXPECT_THAT")
benchmark(expect_eq expect "-DEXPECT_EQ")
benchmark(include include)
benchmark(suite suite)
benchmark(test test)
boost-ext-ut-2.3.1/benchmark/expect.cpp 0000664 0000000 0000000 00000001364 14773232535 0020034 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using namespace boost::ut;
static constexpr auto iterations = 1'000'000;
#if defined(EXPECT_UDL)
"expect_udl"_test = [] {
for (auto i = 0; i < iterations; ++i) {
expect(i == _i(i));
}
};
#elif defined(EXPECT_THAT)
"expect_that"_test = [] {
for (auto i = 0; i < iterations; ++i) {
expect(that % i == i);
}
};
#elif defined(EXPECT_EQ)
"expect_eq"_test = [] {
for (auto i = 0; i < iterations; ++i) {
expect(eq(i, i));
}
};
#endif
}
boost-ext-ut-2.3.1/benchmark/include.cpp 0000664 0000000 0000000 00000000414 14773232535 0020162 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {}
boost-ext-ut-2.3.1/benchmark/suite.cpp 0000664 0000000 0000000 00000005676 14773232535 0017707 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
namespace ut = boost::ut;
ut::suite _1 = [] {
using namespace ut;
"1.1"_test = [] {};
"1.2"_test = [] {};
"1.3"_test = [] {};
"1.4"_test = [] {};
"1.5"_test = [] {};
"1.6"_test = [] {};
"1.7"_test = [] {};
"1.8"_test = [] {};
"1.9"_test = [] {};
"1.10"_test = [] {};
};
ut::suite _2 = [] {
using namespace ut;
"2.1"_test = [] {};
"2.2"_test = [] {};
"2.3"_test = [] {};
"2.4"_test = [] {};
"2.5"_test = [] {};
"2.6"_test = [] {};
"2.7"_test = [] {};
"2.8"_test = [] {};
"2.9"_test = [] {};
"2.10"_test = [] {};
};
ut::suite _3 = [] {
using namespace ut;
"3.1"_test = [] {};
"3.2"_test = [] {};
"3.3"_test = [] {};
"3.4"_test = [] {};
"3.5"_test = [] {};
"3.6"_test = [] {};
"3.7"_test = [] {};
"3.8"_test = [] {};
"3.9"_test = [] {};
"3.10"_test = [] {};
};
ut::suite _4 = [] {
using namespace ut;
"4.1"_test = [] {};
"4.2"_test = [] {};
"4.3"_test = [] {};
"4.4"_test = [] {};
"4.5"_test = [] {};
"4.6"_test = [] {};
"4.7"_test = [] {};
"4.8"_test = [] {};
"4.9"_test = [] {};
"4.10"_test = [] {};
};
#if not defined(WIN32)
ut::suite _5 = [] {
using namespace ut;
"5.1"_test = [] {};
"5.2"_test = [] {};
"5.3"_test = [] {};
"5.4"_test = [] {};
"5.5"_test = [] {};
"5.6"_test = [] {};
"5.7"_test = [] {};
"5.8"_test = [] {};
"5.9"_test = [] {};
"5.10"_test = [] {};
};
ut::suite _6 = [] {
using namespace ut;
"6.1"_test = [] {};
"6.2"_test = [] {};
"6.3"_test = [] {};
"6.4"_test = [] {};
"6.5"_test = [] {};
"6.6"_test = [] {};
"6.7"_test = [] {};
"6.8"_test = [] {};
"6.9"_test = [] {};
"6.10"_test = [] {};
};
ut::suite _7 = [] {
using namespace ut;
"7.1"_test = [] {};
"7.2"_test = [] {};
"7.3"_test = [] {};
"7.4"_test = [] {};
"7.5"_test = [] {};
"7.6"_test = [] {};
"7.7"_test = [] {};
"7.8"_test = [] {};
"7.9"_test = [] {};
"7.10"_test = [] {};
};
ut::suite _8 = [] {
using namespace ut;
"8.1"_test = [] {};
"8.2"_test = [] {};
"8.3"_test = [] {};
"8.4"_test = [] {};
"8.5"_test = [] {};
"8.6"_test = [] {};
"8.7"_test = [] {};
"8.8"_test = [] {};
"8.9"_test = [] {};
"8.10"_test = [] {};
};
ut::suite _9 = [] {
using namespace ut;
"9.1"_test = [] {};
"9.2"_test = [] {};
"9.3"_test = [] {};
"9.4"_test = [] {};
"9.5"_test = [] {};
"9.6"_test = [] {};
"9.7"_test = [] {};
"9.8"_test = [] {};
"9.9"_test = [] {};
"9.10"_test = [] {};
};
ut::suite _10 = [] {
using namespace ut;
"10.1"_test = [] {};
"10.2"_test = [] {};
"10.3"_test = [] {};
"10.4"_test = [] {};
"10.5"_test = [] {};
"10.6"_test = [] {};
"10.7"_test = [] {};
"10.8"_test = [] {};
"10.9"_test = [] {};
"10.10"_test = [] {};
};
#endif
int main() {}
boost-ext-ut-2.3.1/benchmark/test.cpp 0000664 0000000 0000000 00000053260 14773232535 0017525 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using namespace boost::ut;
"1"_test = [] {};
"2"_test = [] {};
"3"_test = [] {};
"4"_test = [] {};
"5"_test = [] {};
"6"_test = [] {};
"7"_test = [] {};
"8"_test = [] {};
"9"_test = [] {};
"10"_test = [] {};
"11"_test = [] {};
"12"_test = [] {};
"13"_test = [] {};
"14"_test = [] {};
"15"_test = [] {};
"16"_test = [] {};
"17"_test = [] {};
"18"_test = [] {};
"19"_test = [] {};
"20"_test = [] {};
"21"_test = [] {};
"22"_test = [] {};
"23"_test = [] {};
"24"_test = [] {};
"25"_test = [] {};
"26"_test = [] {};
"27"_test = [] {};
"28"_test = [] {};
"29"_test = [] {};
"30"_test = [] {};
"31"_test = [] {};
"32"_test = [] {};
"33"_test = [] {};
"34"_test = [] {};
"35"_test = [] {};
"36"_test = [] {};
"37"_test = [] {};
"38"_test = [] {};
"39"_test = [] {};
"40"_test = [] {};
"41"_test = [] {};
"42"_test = [] {};
"43"_test = [] {};
"44"_test = [] {};
"45"_test = [] {};
"46"_test = [] {};
"47"_test = [] {};
"48"_test = [] {};
"49"_test = [] {};
"50"_test = [] {};
"51"_test = [] {};
"52"_test = [] {};
"53"_test = [] {};
"54"_test = [] {};
"55"_test = [] {};
"56"_test = [] {};
"57"_test = [] {};
"58"_test = [] {};
"59"_test = [] {};
"60"_test = [] {};
"61"_test = [] {};
"62"_test = [] {};
"63"_test = [] {};
"64"_test = [] {};
"65"_test = [] {};
"66"_test = [] {};
"67"_test = [] {};
"68"_test = [] {};
"69"_test = [] {};
"70"_test = [] {};
"71"_test = [] {};
"72"_test = [] {};
"73"_test = [] {};
"74"_test = [] {};
"75"_test = [] {};
"76"_test = [] {};
"77"_test = [] {};
"78"_test = [] {};
"79"_test = [] {};
"80"_test = [] {};
"81"_test = [] {};
"82"_test = [] {};
"83"_test = [] {};
"84"_test = [] {};
"85"_test = [] {};
"86"_test = [] {};
"87"_test = [] {};
"88"_test = [] {};
"89"_test = [] {};
"90"_test = [] {};
"91"_test = [] {};
"92"_test = [] {};
"93"_test = [] {};
"94"_test = [] {};
"95"_test = [] {};
"96"_test = [] {};
"97"_test = [] {};
"98"_test = [] {};
"99"_test = [] {};
"100"_test = [] {};
"101"_test = [] {};
"102"_test = [] {};
"103"_test = [] {};
"104"_test = [] {};
"105"_test = [] {};
"106"_test = [] {};
"107"_test = [] {};
"108"_test = [] {};
"109"_test = [] {};
"110"_test = [] {};
"111"_test = [] {};
"112"_test = [] {};
"113"_test = [] {};
"114"_test = [] {};
"115"_test = [] {};
"116"_test = [] {};
"117"_test = [] {};
"118"_test = [] {};
"119"_test = [] {};
"120"_test = [] {};
"121"_test = [] {};
"122"_test = [] {};
"123"_test = [] {};
"124"_test = [] {};
"125"_test = [] {};
"126"_test = [] {};
"127"_test = [] {};
"128"_test = [] {};
"129"_test = [] {};
"130"_test = [] {};
"131"_test = [] {};
"132"_test = [] {};
"133"_test = [] {};
"134"_test = [] {};
"135"_test = [] {};
"136"_test = [] {};
"137"_test = [] {};
"138"_test = [] {};
"139"_test = [] {};
"140"_test = [] {};
"141"_test = [] {};
"142"_test = [] {};
"143"_test = [] {};
"144"_test = [] {};
"145"_test = [] {};
"146"_test = [] {};
"147"_test = [] {};
"148"_test = [] {};
"149"_test = [] {};
"150"_test = [] {};
"151"_test = [] {};
"152"_test = [] {};
"153"_test = [] {};
"154"_test = [] {};
"155"_test = [] {};
"156"_test = [] {};
"157"_test = [] {};
"158"_test = [] {};
"159"_test = [] {};
"160"_test = [] {};
"161"_test = [] {};
"162"_test = [] {};
"163"_test = [] {};
"164"_test = [] {};
"165"_test = [] {};
"166"_test = [] {};
"167"_test = [] {};
"168"_test = [] {};
"169"_test = [] {};
"170"_test = [] {};
"171"_test = [] {};
"172"_test = [] {};
"173"_test = [] {};
"174"_test = [] {};
"175"_test = [] {};
"176"_test = [] {};
"177"_test = [] {};
"178"_test = [] {};
"179"_test = [] {};
"180"_test = [] {};
"181"_test = [] {};
"182"_test = [] {};
"183"_test = [] {};
"184"_test = [] {};
"185"_test = [] {};
"186"_test = [] {};
"187"_test = [] {};
"188"_test = [] {};
"189"_test = [] {};
"190"_test = [] {};
"191"_test = [] {};
"192"_test = [] {};
"193"_test = [] {};
"194"_test = [] {};
"195"_test = [] {};
"196"_test = [] {};
"197"_test = [] {};
"198"_test = [] {};
"199"_test = [] {};
"200"_test = [] {};
"201"_test = [] {};
"202"_test = [] {};
"203"_test = [] {};
"204"_test = [] {};
"205"_test = [] {};
"206"_test = [] {};
"207"_test = [] {};
"208"_test = [] {};
"209"_test = [] {};
"210"_test = [] {};
"211"_test = [] {};
"212"_test = [] {};
"213"_test = [] {};
"214"_test = [] {};
"215"_test = [] {};
"216"_test = [] {};
"217"_test = [] {};
"218"_test = [] {};
"219"_test = [] {};
"220"_test = [] {};
"221"_test = [] {};
"222"_test = [] {};
"223"_test = [] {};
"224"_test = [] {};
"225"_test = [] {};
"226"_test = [] {};
"227"_test = [] {};
"228"_test = [] {};
"229"_test = [] {};
"230"_test = [] {};
"231"_test = [] {};
"232"_test = [] {};
"233"_test = [] {};
"234"_test = [] {};
"235"_test = [] {};
"236"_test = [] {};
"237"_test = [] {};
"238"_test = [] {};
"239"_test = [] {};
"240"_test = [] {};
"241"_test = [] {};
"242"_test = [] {};
"243"_test = [] {};
"244"_test = [] {};
"245"_test = [] {};
"246"_test = [] {};
"247"_test = [] {};
"248"_test = [] {};
"249"_test = [] {};
"250"_test = [] {};
"251"_test = [] {};
"252"_test = [] {};
"253"_test = [] {};
"254"_test = [] {};
"255"_test = [] {};
"256"_test = [] {};
"257"_test = [] {};
"258"_test = [] {};
"259"_test = [] {};
"260"_test = [] {};
"261"_test = [] {};
"262"_test = [] {};
"263"_test = [] {};
"264"_test = [] {};
"265"_test = [] {};
"266"_test = [] {};
"267"_test = [] {};
"268"_test = [] {};
"269"_test = [] {};
"270"_test = [] {};
"271"_test = [] {};
"272"_test = [] {};
"273"_test = [] {};
"274"_test = [] {};
"275"_test = [] {};
"276"_test = [] {};
"277"_test = [] {};
"278"_test = [] {};
"279"_test = [] {};
"280"_test = [] {};
"281"_test = [] {};
"282"_test = [] {};
"283"_test = [] {};
"284"_test = [] {};
"285"_test = [] {};
"286"_test = [] {};
"287"_test = [] {};
"288"_test = [] {};
"289"_test = [] {};
"290"_test = [] {};
"291"_test = [] {};
"292"_test = [] {};
"293"_test = [] {};
"294"_test = [] {};
"295"_test = [] {};
"296"_test = [] {};
"297"_test = [] {};
"298"_test = [] {};
"299"_test = [] {};
"300"_test = [] {};
"301"_test = [] {};
"302"_test = [] {};
"303"_test = [] {};
"304"_test = [] {};
"305"_test = [] {};
"306"_test = [] {};
"307"_test = [] {};
"308"_test = [] {};
"309"_test = [] {};
"310"_test = [] {};
"311"_test = [] {};
"312"_test = [] {};
"313"_test = [] {};
"314"_test = [] {};
"315"_test = [] {};
"316"_test = [] {};
"317"_test = [] {};
"318"_test = [] {};
"319"_test = [] {};
"320"_test = [] {};
"321"_test = [] {};
"322"_test = [] {};
"323"_test = [] {};
"324"_test = [] {};
"325"_test = [] {};
"326"_test = [] {};
"327"_test = [] {};
"328"_test = [] {};
"329"_test = [] {};
"330"_test = [] {};
"331"_test = [] {};
"332"_test = [] {};
"333"_test = [] {};
"334"_test = [] {};
"335"_test = [] {};
"336"_test = [] {};
"337"_test = [] {};
"338"_test = [] {};
"339"_test = [] {};
"340"_test = [] {};
"341"_test = [] {};
"342"_test = [] {};
"343"_test = [] {};
"344"_test = [] {};
"345"_test = [] {};
"346"_test = [] {};
"347"_test = [] {};
"348"_test = [] {};
"349"_test = [] {};
"350"_test = [] {};
"351"_test = [] {};
"352"_test = [] {};
"353"_test = [] {};
"354"_test = [] {};
"355"_test = [] {};
"356"_test = [] {};
"357"_test = [] {};
"358"_test = [] {};
"359"_test = [] {};
"360"_test = [] {};
"361"_test = [] {};
"362"_test = [] {};
"363"_test = [] {};
"364"_test = [] {};
"365"_test = [] {};
"366"_test = [] {};
"367"_test = [] {};
"368"_test = [] {};
"369"_test = [] {};
"370"_test = [] {};
"371"_test = [] {};
"372"_test = [] {};
"373"_test = [] {};
"374"_test = [] {};
"375"_test = [] {};
"376"_test = [] {};
"377"_test = [] {};
"378"_test = [] {};
"379"_test = [] {};
"380"_test = [] {};
"381"_test = [] {};
"382"_test = [] {};
"383"_test = [] {};
"384"_test = [] {};
"385"_test = [] {};
"386"_test = [] {};
"387"_test = [] {};
"388"_test = [] {};
"389"_test = [] {};
"390"_test = [] {};
"391"_test = [] {};
"392"_test = [] {};
"393"_test = [] {};
"394"_test = [] {};
"395"_test = [] {};
"396"_test = [] {};
"397"_test = [] {};
"398"_test = [] {};
"399"_test = [] {};
"400"_test = [] {};
"401"_test = [] {};
"402"_test = [] {};
"403"_test = [] {};
"404"_test = [] {};
"405"_test = [] {};
"406"_test = [] {};
"407"_test = [] {};
"408"_test = [] {};
"409"_test = [] {};
"410"_test = [] {};
"411"_test = [] {};
"412"_test = [] {};
"413"_test = [] {};
"414"_test = [] {};
"415"_test = [] {};
"416"_test = [] {};
"417"_test = [] {};
"418"_test = [] {};
"419"_test = [] {};
"420"_test = [] {};
"421"_test = [] {};
"422"_test = [] {};
"423"_test = [] {};
"424"_test = [] {};
"425"_test = [] {};
"426"_test = [] {};
"427"_test = [] {};
"428"_test = [] {};
"429"_test = [] {};
"430"_test = [] {};
"431"_test = [] {};
"432"_test = [] {};
"433"_test = [] {};
"434"_test = [] {};
"435"_test = [] {};
"436"_test = [] {};
"437"_test = [] {};
"438"_test = [] {};
"439"_test = [] {};
"440"_test = [] {};
"441"_test = [] {};
"442"_test = [] {};
"443"_test = [] {};
"444"_test = [] {};
"445"_test = [] {};
"446"_test = [] {};
"447"_test = [] {};
"448"_test = [] {};
"449"_test = [] {};
"450"_test = [] {};
"451"_test = [] {};
"452"_test = [] {};
"453"_test = [] {};
"454"_test = [] {};
"455"_test = [] {};
"456"_test = [] {};
"457"_test = [] {};
"458"_test = [] {};
"459"_test = [] {};
"460"_test = [] {};
"461"_test = [] {};
"462"_test = [] {};
"463"_test = [] {};
"464"_test = [] {};
"465"_test = [] {};
"466"_test = [] {};
"467"_test = [] {};
"468"_test = [] {};
"469"_test = [] {};
"470"_test = [] {};
"471"_test = [] {};
"472"_test = [] {};
"473"_test = [] {};
"474"_test = [] {};
"475"_test = [] {};
"476"_test = [] {};
"477"_test = [] {};
"478"_test = [] {};
"479"_test = [] {};
"480"_test = [] {};
"481"_test = [] {};
"482"_test = [] {};
"483"_test = [] {};
"484"_test = [] {};
"485"_test = [] {};
"486"_test = [] {};
"487"_test = [] {};
"488"_test = [] {};
"489"_test = [] {};
"490"_test = [] {};
"491"_test = [] {};
"492"_test = [] {};
"493"_test = [] {};
"494"_test = [] {};
"495"_test = [] {};
"496"_test = [] {};
"497"_test = [] {};
"498"_test = [] {};
"499"_test = [] {};
"500"_test = [] {};
"501"_test = [] {};
"502"_test = [] {};
"503"_test = [] {};
"504"_test = [] {};
"505"_test = [] {};
"506"_test = [] {};
"507"_test = [] {};
"508"_test = [] {};
"509"_test = [] {};
"510"_test = [] {};
"511"_test = [] {};
"512"_test = [] {};
"513"_test = [] {};
"514"_test = [] {};
"515"_test = [] {};
"516"_test = [] {};
"517"_test = [] {};
"518"_test = [] {};
"519"_test = [] {};
"520"_test = [] {};
"521"_test = [] {};
"522"_test = [] {};
"523"_test = [] {};
"524"_test = [] {};
"525"_test = [] {};
"526"_test = [] {};
"527"_test = [] {};
"528"_test = [] {};
"529"_test = [] {};
"530"_test = [] {};
"531"_test = [] {};
"532"_test = [] {};
"533"_test = [] {};
"534"_test = [] {};
"535"_test = [] {};
"536"_test = [] {};
"537"_test = [] {};
"538"_test = [] {};
"539"_test = [] {};
"540"_test = [] {};
"541"_test = [] {};
"542"_test = [] {};
"543"_test = [] {};
"544"_test = [] {};
"545"_test = [] {};
"546"_test = [] {};
"547"_test = [] {};
"548"_test = [] {};
"549"_test = [] {};
"550"_test = [] {};
"551"_test = [] {};
"552"_test = [] {};
"553"_test = [] {};
"554"_test = [] {};
"555"_test = [] {};
"556"_test = [] {};
"557"_test = [] {};
"558"_test = [] {};
"559"_test = [] {};
"560"_test = [] {};
"561"_test = [] {};
"562"_test = [] {};
"563"_test = [] {};
"564"_test = [] {};
"565"_test = [] {};
"566"_test = [] {};
"567"_test = [] {};
"568"_test = [] {};
"569"_test = [] {};
"570"_test = [] {};
"571"_test = [] {};
"572"_test = [] {};
"573"_test = [] {};
"574"_test = [] {};
"575"_test = [] {};
"576"_test = [] {};
"577"_test = [] {};
"578"_test = [] {};
"579"_test = [] {};
"580"_test = [] {};
"581"_test = [] {};
"582"_test = [] {};
"583"_test = [] {};
"584"_test = [] {};
"585"_test = [] {};
"586"_test = [] {};
"587"_test = [] {};
"588"_test = [] {};
"589"_test = [] {};
"590"_test = [] {};
"591"_test = [] {};
"592"_test = [] {};
"593"_test = [] {};
"594"_test = [] {};
"595"_test = [] {};
"596"_test = [] {};
"597"_test = [] {};
"598"_test = [] {};
"599"_test = [] {};
"600"_test = [] {};
"601"_test = [] {};
"602"_test = [] {};
"603"_test = [] {};
"604"_test = [] {};
"605"_test = [] {};
"606"_test = [] {};
"607"_test = [] {};
"608"_test = [] {};
"609"_test = [] {};
"610"_test = [] {};
"611"_test = [] {};
"612"_test = [] {};
"613"_test = [] {};
"614"_test = [] {};
"615"_test = [] {};
"616"_test = [] {};
"617"_test = [] {};
"618"_test = [] {};
"619"_test = [] {};
"620"_test = [] {};
"621"_test = [] {};
"622"_test = [] {};
"623"_test = [] {};
"624"_test = [] {};
"625"_test = [] {};
"626"_test = [] {};
"627"_test = [] {};
"628"_test = [] {};
"629"_test = [] {};
"630"_test = [] {};
"631"_test = [] {};
"632"_test = [] {};
"633"_test = [] {};
"634"_test = [] {};
"635"_test = [] {};
"636"_test = [] {};
"637"_test = [] {};
"638"_test = [] {};
"639"_test = [] {};
"640"_test = [] {};
"641"_test = [] {};
"642"_test = [] {};
"643"_test = [] {};
"644"_test = [] {};
"645"_test = [] {};
"646"_test = [] {};
"647"_test = [] {};
"648"_test = [] {};
"649"_test = [] {};
"650"_test = [] {};
"651"_test = [] {};
"652"_test = [] {};
"653"_test = [] {};
"654"_test = [] {};
"655"_test = [] {};
"656"_test = [] {};
"657"_test = [] {};
"658"_test = [] {};
"659"_test = [] {};
"660"_test = [] {};
"661"_test = [] {};
"662"_test = [] {};
"663"_test = [] {};
"664"_test = [] {};
"665"_test = [] {};
"666"_test = [] {};
"667"_test = [] {};
"668"_test = [] {};
"669"_test = [] {};
"670"_test = [] {};
"671"_test = [] {};
"672"_test = [] {};
"673"_test = [] {};
"674"_test = [] {};
"675"_test = [] {};
"676"_test = [] {};
"677"_test = [] {};
"678"_test = [] {};
"679"_test = [] {};
"680"_test = [] {};
"681"_test = [] {};
"682"_test = [] {};
"683"_test = [] {};
"684"_test = [] {};
"685"_test = [] {};
"686"_test = [] {};
"687"_test = [] {};
"688"_test = [] {};
"689"_test = [] {};
"690"_test = [] {};
"691"_test = [] {};
"692"_test = [] {};
"693"_test = [] {};
"694"_test = [] {};
"695"_test = [] {};
"696"_test = [] {};
"697"_test = [] {};
"698"_test = [] {};
"699"_test = [] {};
"700"_test = [] {};
"701"_test = [] {};
"702"_test = [] {};
"703"_test = [] {};
"704"_test = [] {};
"705"_test = [] {};
"706"_test = [] {};
"707"_test = [] {};
"708"_test = [] {};
"709"_test = [] {};
"710"_test = [] {};
"711"_test = [] {};
"712"_test = [] {};
"713"_test = [] {};
"714"_test = [] {};
"715"_test = [] {};
"716"_test = [] {};
"717"_test = [] {};
"718"_test = [] {};
"719"_test = [] {};
"720"_test = [] {};
"721"_test = [] {};
"722"_test = [] {};
"723"_test = [] {};
"724"_test = [] {};
"725"_test = [] {};
"726"_test = [] {};
"727"_test = [] {};
"728"_test = [] {};
"729"_test = [] {};
"730"_test = [] {};
"731"_test = [] {};
"732"_test = [] {};
"733"_test = [] {};
"734"_test = [] {};
"735"_test = [] {};
"736"_test = [] {};
"737"_test = [] {};
"738"_test = [] {};
"739"_test = [] {};
"740"_test = [] {};
"741"_test = [] {};
"742"_test = [] {};
"743"_test = [] {};
"744"_test = [] {};
"745"_test = [] {};
"746"_test = [] {};
"747"_test = [] {};
"748"_test = [] {};
"749"_test = [] {};
"750"_test = [] {};
"751"_test = [] {};
"752"_test = [] {};
"753"_test = [] {};
"754"_test = [] {};
"755"_test = [] {};
"756"_test = [] {};
"757"_test = [] {};
"758"_test = [] {};
"759"_test = [] {};
"760"_test = [] {};
"761"_test = [] {};
"762"_test = [] {};
"763"_test = [] {};
"764"_test = [] {};
"765"_test = [] {};
"766"_test = [] {};
"767"_test = [] {};
"768"_test = [] {};
"769"_test = [] {};
"770"_test = [] {};
"771"_test = [] {};
"772"_test = [] {};
"773"_test = [] {};
"774"_test = [] {};
"775"_test = [] {};
"776"_test = [] {};
"777"_test = [] {};
"778"_test = [] {};
"779"_test = [] {};
"780"_test = [] {};
"781"_test = [] {};
"782"_test = [] {};
"783"_test = [] {};
"784"_test = [] {};
"785"_test = [] {};
"786"_test = [] {};
"787"_test = [] {};
"788"_test = [] {};
"789"_test = [] {};
"790"_test = [] {};
"791"_test = [] {};
"792"_test = [] {};
"793"_test = [] {};
"794"_test = [] {};
"795"_test = [] {};
"796"_test = [] {};
"797"_test = [] {};
"798"_test = [] {};
"799"_test = [] {};
"800"_test = [] {};
"801"_test = [] {};
"802"_test = [] {};
"803"_test = [] {};
"804"_test = [] {};
"805"_test = [] {};
"806"_test = [] {};
"807"_test = [] {};
"808"_test = [] {};
"809"_test = [] {};
"810"_test = [] {};
"811"_test = [] {};
"812"_test = [] {};
"813"_test = [] {};
"814"_test = [] {};
"815"_test = [] {};
"816"_test = [] {};
"817"_test = [] {};
"818"_test = [] {};
"819"_test = [] {};
"820"_test = [] {};
"821"_test = [] {};
"822"_test = [] {};
"823"_test = [] {};
"824"_test = [] {};
"825"_test = [] {};
"826"_test = [] {};
"827"_test = [] {};
"828"_test = [] {};
"829"_test = [] {};
"830"_test = [] {};
"831"_test = [] {};
"832"_test = [] {};
"833"_test = [] {};
"834"_test = [] {};
"835"_test = [] {};
"836"_test = [] {};
"837"_test = [] {};
"838"_test = [] {};
"839"_test = [] {};
"840"_test = [] {};
"841"_test = [] {};
"842"_test = [] {};
"843"_test = [] {};
"844"_test = [] {};
"845"_test = [] {};
"846"_test = [] {};
"847"_test = [] {};
"848"_test = [] {};
"849"_test = [] {};
"850"_test = [] {};
"851"_test = [] {};
"852"_test = [] {};
"853"_test = [] {};
"854"_test = [] {};
"855"_test = [] {};
"856"_test = [] {};
"857"_test = [] {};
"858"_test = [] {};
"859"_test = [] {};
"860"_test = [] {};
"861"_test = [] {};
"862"_test = [] {};
"863"_test = [] {};
"864"_test = [] {};
"865"_test = [] {};
"866"_test = [] {};
"867"_test = [] {};
"868"_test = [] {};
"869"_test = [] {};
"870"_test = [] {};
"871"_test = [] {};
"872"_test = [] {};
"873"_test = [] {};
"874"_test = [] {};
"875"_test = [] {};
"876"_test = [] {};
"877"_test = [] {};
"878"_test = [] {};
"879"_test = [] {};
"880"_test = [] {};
"881"_test = [] {};
"882"_test = [] {};
"883"_test = [] {};
"884"_test = [] {};
"885"_test = [] {};
"886"_test = [] {};
"887"_test = [] {};
"888"_test = [] {};
"889"_test = [] {};
"890"_test = [] {};
"891"_test = [] {};
"892"_test = [] {};
"893"_test = [] {};
"894"_test = [] {};
"895"_test = [] {};
"896"_test = [] {};
"897"_test = [] {};
"898"_test = [] {};
"899"_test = [] {};
"900"_test = [] {};
"901"_test = [] {};
"902"_test = [] {};
"903"_test = [] {};
"904"_test = [] {};
"905"_test = [] {};
"906"_test = [] {};
"907"_test = [] {};
"908"_test = [] {};
"909"_test = [] {};
"910"_test = [] {};
"911"_test = [] {};
"912"_test = [] {};
"913"_test = [] {};
"914"_test = [] {};
"915"_test = [] {};
"916"_test = [] {};
"917"_test = [] {};
"918"_test = [] {};
"919"_test = [] {};
"920"_test = [] {};
"921"_test = [] {};
"922"_test = [] {};
"923"_test = [] {};
"924"_test = [] {};
"925"_test = [] {};
"926"_test = [] {};
"927"_test = [] {};
"928"_test = [] {};
"929"_test = [] {};
"930"_test = [] {};
"931"_test = [] {};
"932"_test = [] {};
"933"_test = [] {};
"934"_test = [] {};
"935"_test = [] {};
"936"_test = [] {};
"937"_test = [] {};
"938"_test = [] {};
"939"_test = [] {};
"940"_test = [] {};
"941"_test = [] {};
"942"_test = [] {};
"943"_test = [] {};
"944"_test = [] {};
"945"_test = [] {};
"946"_test = [] {};
"947"_test = [] {};
"948"_test = [] {};
"949"_test = [] {};
"950"_test = [] {};
"951"_test = [] {};
"952"_test = [] {};
"953"_test = [] {};
"954"_test = [] {};
"955"_test = [] {};
"956"_test = [] {};
"957"_test = [] {};
"958"_test = [] {};
"959"_test = [] {};
"960"_test = [] {};
"961"_test = [] {};
"962"_test = [] {};
"963"_test = [] {};
"964"_test = [] {};
"965"_test = [] {};
"966"_test = [] {};
"967"_test = [] {};
"968"_test = [] {};
"969"_test = [] {};
"970"_test = [] {};
"971"_test = [] {};
"972"_test = [] {};
"973"_test = [] {};
"974"_test = [] {};
"975"_test = [] {};
"976"_test = [] {};
"977"_test = [] {};
"978"_test = [] {};
"979"_test = [] {};
"980"_test = [] {};
"981"_test = [] {};
"982"_test = [] {};
"983"_test = [] {};
"984"_test = [] {};
"985"_test = [] {};
"986"_test = [] {};
"987"_test = [] {};
"988"_test = [] {};
"989"_test = [] {};
"990"_test = [] {};
"991"_test = [] {};
"992"_test = [] {};
"993"_test = [] {};
"994"_test = [] {};
"995"_test = [] {};
"996"_test = [] {};
"997"_test = [] {};
"998"_test = [] {};
"999"_test = [] {};
"1000"_test = [] {};
}
boost-ext-ut-2.3.1/cmake/ 0000775 0000000 0000000 00000000000 14773232535 0015162 5 ustar 00root root 0000000 0000000 boost-ext-ut-2.3.1/cmake/AddCustomCommandOrTest.cmake 0000664 0000000 0000000 00000001452 14773232535 0022511 0 ustar 00root root 0000000 0000000 option(BOOST_UT_ENABLE_RUN_AFTER_BUILD "Automatically run built artifacts. If disabled, the tests can be run with ctest instead" ON)
function(ut_add_custom_command_or_test)
# Define the supported set of keywords
set(prefix "PARSE")
set(noValues "")
set(singleValues TARGET)
set(multiValues COMMAND)
# Process the arguments passed in
include(CMakeParseArguments)
cmake_parse_arguments("${prefix}" "${noValues}" "${singleValues}" "${multiValues}" ${ARGN})
target_link_libraries(${PARSE_TARGET} PRIVATE Boost::ut)
if(BOOST_UT_ENABLE_RUN_AFTER_BUILD)
add_custom_command(
TARGET ${PARSE_TARGET}
POST_BUILD
COMMAND ${PARSE_COMMAND}
COMMENT "Running ${PARSE_TARGET}"
)
else()
add_test(NAME ${PARSE_TARGET} COMMAND ${PARSE_COMMAND})
endif()
endfunction()
boost-ext-ut-2.3.1/cmake/WarningsAsErrors.cmake 0000664 0000000 0000000 00000001055 14773232535 0021436 0 ustar 00root root 0000000 0000000 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC")
add_compile_options(/W4 /WX)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
add_compile_options(-Wall -Wextra -Wpedantic -Werror -Wshadow)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 10.0)
add_compile_options(-Wdeprecated-copy-dtor -Wnewline-eof)
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
string(REGEX REPLACE " /W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
add_compile_options(/W4 /WX)
endif()
boost-ext-ut-2.3.1/example/ 0000775 0000000 0000000 00000000000 14773232535 0015535 5 ustar 00root root 0000000 0000000 boost-ext-ut-2.3.1/example/BDD.cpp 0000664 0000000 0000000 00000002147 14773232535 0016636 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using namespace boost::ut::literals;
using namespace boost::ut::operators::terse;
using namespace boost::ut::bdd;
"Scenario"_test = [] {
given("I have...") = [] {
when("I run...") = [] {
then("I should have...") = [] { 1_u == 1u; };
then("I should have...") = [] { 1u == 1_u; };
};
};
};
feature("Calculator") = [] {
scenario("Addition") = [] {
given("I have number 40") = [] {
auto number = 40;
when("I add 2 to number") = [&number] { number += 2; };
then("I expect number to be 42") = [&number] { 42_i == number; };
};
};
};
// clang-format off
scenario("Addition");
given("I have number 40");
auto number = 40;
when("I add 2 to number");
number += 2;
then("I expect number to be 42");
42_i == number;
// clang-format on
}
boost-ext-ut-2.3.1/example/CMakeLists.txt 0000664 0000000 0000000 00000004674 14773232535 0020310 0 ustar 00root root 0000000 0000000 #
# Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
find_program(BOOST_UT_MEMORYCHECK_COMMAND valgrind)
function(example file target)
add_executable(boost_ut_${target} ${file}.cpp)
if(BOOST_UT_ENABLE_MEMCHECK AND BOOST_UT_MEMORYCHECK_COMMAND)
ut_add_custom_command_or_test(
TARGET
boost_ut_${target}
COMMAND
${BOOST_UT_MEMORYCHECK_COMMAND}
--leak-check=full
--error-exitcode=1
./boost_ut_${target}
${ARGN}
)
else()
ut_add_custom_command_or_test(TARGET boost_ut_${target} COMMAND boost_ut_${target} ${ARGN})
endif()
endfunction()
example(cfg/printer printer)
example(cfg/runner runner)
if(APPLE OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
example(cfg/parallel_runner parallel_runner)
endif()
# if(DEFINED ENV{TBB_ROOT})
# set(TBB_ROOT $ENV{TBB_ROOT})
# # FIXME: include could not find load file:
# include(${TBB_ROOT}/cmake/TBBBuild.cmake)
# tbb_build(TBB_ROOT ${TBB_ROOT} CONFIG_DIR TBB_DIR MAKE_ARGS stdver="c++17")
# find_package(TBB)
# target_link_libraries(boost_ut_parallel_runner ${TBB_IMPORTED_TARGETS})
# endif()
example(cfg/reporter reporter)
if(NOT WIN32)
example(abort abort)
endif()
example(attr attr)
example(BDD BDD)
example(benchmark benchmark)
example(cli cli_pass "cli.pass")
example(cli cli_pass_no_colors "cli.pass" "0" "1")
example(cli cli_pass_dry_run "cli.pass" "1" "1")
example(cli cli_pass_not_dry_run "cli.pass" "1" "0")
example(cli cli_all_dry_run "\\*" "1" "1")
example(cli cli_fail_dry_run "cli.fail" "1" "1")
example(exception exception)
example(expect expect)
example(fatal fatal)
example(filter filter)
if(NOT WIN32 AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
example(gherkin gherkin)
example(gherkin gherkin_feature "../../example/gherkin.feature")
endif()
example(hello_world hello_world)
example(log log)
example(macro macro)
example(main main '')
example(minimal minimal)
example(mut mut)
example(matcher matcher)
if(NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang")
example(parameterized parameterized)
endif()
example(run run)
example(run_report run_report)
example(section section)
example(should should)
example(skip skip)
example(sl sl)
example(spec spec)
example(suite suite)
example(tag tag)
example(terse terse)
example(test _test)
example(tmp tmp)
example(using using)
boost-ext-ut-2.3.1/example/abort.cpp 0000664 0000000 0000000 00000000724 14773232535 0017353 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#undef NDEBUG
#include
int main() {
using namespace boost::ut;
"abort"_test = [] {
expect(not aborts([] {}));
expect(aborts([] { assert(false); }));
expect(aborts([] { throw; }));
};
}
boost-ext-ut-2.3.1/example/attr.cpp 0000664 0000000 0000000 00000001326 14773232535 0017215 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
constexpr auto sum = [](auto... args) { return (0 + ... + args); };
int main() {
using boost::ut::operator""_test;
using namespace boost::ut::literals;
using namespace boost::ut::operators::terse;
"macro"_test = [] {
#define expect void(),
expect sum(1, 1) == 2_i;
expect(6_i == sum(1, 2, 3));
#undef expect
};
#if __has_cpp_attribute(expect)
"attribute"_test = [] {
[[expect]] 3_i == sum(1, 2);
[[expect]] (sum(1, 2) == 3_i);
};
#endif
}
boost-ext-ut-2.3.1/example/benchmark.cpp 0000664 0000000 0000000 00000003235 14773232535 0020176 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
#include
#include
#include
namespace benchmark {
struct benchmark : boost::ut::detail::test {
explicit benchmark(std::string_view _name)
: boost::ut::detail::test{"benchmark", _name} {}
template
auto operator=(Test _test) {
static_cast(*this) = [&_test, this] {
const auto start = std::chrono::high_resolution_clock::now();
_test();
const auto stop = std::chrono::high_resolution_clock::now();
const auto ns =
std::chrono::duration_cast(stop - start);
std::clog << "[" << name << "] " << ns.count() << " ns\n";
};
}
};
[[nodiscard]] auto operator""_benchmark(const char* _name,
decltype(sizeof("")) size) {
return ::benchmark::benchmark{{_name, size}};
}
#if defined(__GNUC__) or defined(__clang__)
template
void do_not_optimize(T&& t) {
asm volatile("" ::"m"(t) : "memory");
}
#else
#pragma optimize("", off)
template
void do_not_optimize(T&& t) {
reinterpret_cast(t) =
reinterpret_cast(t);
}
#pragma optimize("", on)
#endif
} // namespace benchmark
int main() {
using namespace boost::ut;
using namespace benchmark;
"string creation"_benchmark = [] {
std::string created_string{"hello"};
do_not_optimize(created_string);
};
}
boost-ext-ut-2.3.1/example/cfg/ 0000775 0000000 0000000 00000000000 14773232535 0016274 5 ustar 00root root 0000000 0000000 boost-ext-ut-2.3.1/example/cfg/parallel_runner.cpp 0000664 0000000 0000000 00000003106 14773232535 0022165 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
#include
#if __has_include()
#include
#endif
namespace ut = boost::ut;
namespace cfg {
class parallel_runner : public ut::runner<> {
public:
using ut::runner<>::on;
template
auto on(ut::events::test test) {
std::clog << test.name << '\n';
ut::runner<>::on(test);
}
[[nodiscard]] auto run() -> bool {
#if defined(__cpp_lib_parallel_algorithm)
std::for_each(std::execution::par, std::cbegin(suites_), std::cend(suites_),
[&](const auto& suite) { suite.first(); });
#else
std::for_each(std::cbegin(suites_), std::cend(suites_),
[&](const auto& suite) { suite.first(); });
#endif
suites_.clear();
return fails_ > 0;
}
};
} // namespace cfg
template
inline auto ut::cfg = cfg::parallel_runner{};
ut::suite parallel_1 = [] {
using namespace ut;
// sequential
"test.1.1"_test = [] { expect(1_i == 1); };
"test.1.2"_test = [] { expect(2_i == 2); };
"test.1.3"_test = [] { expect(3_i == 3); };
};
ut::suite parallel_2 = [] {
using namespace ut;
// sequential
"test.2.1"_test = [] { expect(1_i == 1); };
"test.2.2"_test = [] { expect(2_i == 2); };
"test.2.3"_test = [] { expect(3_i == 3); };
};
int main() { return ut::cfg.run(); }
boost-ext-ut-2.3.1/example/cfg/printer.cpp 0000664 0000000 0000000 00000001206 14773232535 0020462 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
#include
namespace ut = boost::ut;
namespace cfg {
struct printer : ut::printer {
template
auto& operator<<(T&& t) {
std::cerr << std::forward(t);
return *this;
}
};
} // namespace cfg
template <>
auto ut::cfg = ut::runner>{};
int main() {
using namespace ut;
"printer"_test = [] {};
}
boost-ext-ut-2.3.1/example/cfg/reporter.cpp 0000664 0000000 0000000 00000002262 14773232535 0020644 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
namespace ut = boost::ut;
namespace cfg {
class reporter {
public:
auto on(ut::events::test_begin) -> void {}
auto on(ut::events::test_run) -> void {}
auto on(ut::events::test_skip) -> void {}
auto on(ut::events::test_end) -> void {}
template
auto on(ut::events::log) -> void {}
template
auto on(ut::events::assertion_pass) -> void {}
template
auto on(ut::events::assertion_fail) -> void {}
auto on(ut::events::fatal_assertion) -> void {}
auto on(ut::events::exception) -> void {}
auto on(ut::events::summary) -> void {}
auto on(ut::events::run_begin) -> void {}
};
} // namespace cfg
template <>
auto ut::cfg = ut::runner{};
int main() {
using namespace ut;
using namespace std::literals::string_view_literals;
"example"_test = [] {
expect(42 == 42_i);
expect("ut"sv != "tu"sv);
};
}
boost-ext-ut-2.3.1/example/cfg/runner.cpp 0000664 0000000 0000000 00000001671 14773232535 0020316 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
namespace ut = boost::ut;
namespace cfg {
class runner {
public:
template
auto on(ut::events::test test) {
test();
}
template
auto on(ut::events::skip) {}
template
auto on(ut::events::assertion) -> bool {
return true;
}
auto on(ut::events::fatal_assertion) {}
template
auto on(ut::events::log) {}
};
} // namespace cfg
template <>
auto ut::cfg = cfg::runner{};
int main() {
using namespace ut;
"should be ignored"_test = [] {
expect(throws([] { throw std::runtime_error{"exception!"}; }));
expect(1_i == 2) << "doesn't fire";
};
}
boost-ext-ut-2.3.1/example/cli.cpp 0000664 0000000 0000000 00000001355 14773232535 0017014 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main(int argc, const char** argv) {
using namespace boost::ut;
cfg = {.filter = argc > 1 ? argv[1] : "",
.colors = argc > 2 and argv[2][0] == '0'
? colors{.none = "", .pass = "", .fail = ""}
: colors{},
.dry_run = argc > 3 ? argv[3][0] == '1' : false};
"cli"_test = [] {
"pass"_test = [] { expect(42 == 42_i); };
"fail"_test = [] { expect(0 == 42_i); };
};
}
boost-ext-ut-2.3.1/example/exception.cpp 0000664 0000000 0000000 00000001112 14773232535 0020232 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
int main() {
using namespace boost::ut;
"exceptions"_test = [] {
expect(throws([] {
throw std::runtime_error{"exception!"};
})) << "throws runtime_error";
expect(throws([] { throw 0; })) << "throws any exception";
expect(nothrow([] {})) << "doesn't throw";
};
}
boost-ext-ut-2.3.1/example/expect.cpp 0000664 0000000 0000000 00000006763 14773232535 0017545 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
#include
#include
#include
constexpr auto sum = [](auto... args) { return (0 + ... + args); };
struct dummy_struct {};
int main() {
using namespace boost::ut;
"operators"_test = [] {
expect(0_i == sum());
expect(2_i != sum(1, 2));
expect(sum(1) >= 0_i);
expect(sum(1) <= 1_i);
};
"message"_test = [] { expect(3_i == sum(1, 2)) << "wrong sum"; };
"expressions"_test = [] {
expect(0_i == sum() and 42_i == sum(40, 2));
expect(1_i == sum() or 0_i == sum());
expect(1_i == sum() or (sum() != 0_i or sum(1) > 0_i)) << "compound";
};
"that"_test = [] {
expect(that % 0 == sum());
expect(that % 42 == sum(40, 2) and that % (1 + 2) == sum(1, 2));
expect(that % 1 != 2 or 2_i > 3);
};
"eq/neq/gt/ge/lt/le"_test = [] {
// type_traits::is_stream_insertable_v constraint check
static_assert(type_traits::is_stream_insertable_v);
static_assert(!type_traits::is_stream_insertable_v);
// it seems it produces nice error information
// leaving this as easy way to check failing compilation in case of doubt
// expect(eq(dummy_struct{}, sum(40, 2)));
// gcc
// expect.cpp:46:14: error: no matching function for call to âeq(dummy_struct, int)â
// 46 | expect(eq(dummy_struct{}, sum(40, 2)));
// | ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
// clang
// expect.cpp:51:12: error: no matching function for call to 'eq'
// 51 | expect(eq(dummy_struct{}, sum(40, 2)));
// | ^~
expect(eq(42, sum(40, 2)));
expect(neq(1, 2));
expect(eq(sum(1), 1) and neq(sum(1, 2), 2));
expect(eq(1, 1) and that % 1 == 1 and 1_i == 1);
};
"floating points"_test = [] {
expect(42.1_d == 42.101) << "epsilon=0.1";
expect(42.10_d == 42.101) << "epsilon=0.01";
expect(42.10000001 == 42.1_d) << "epsilon=0.1";
};
"strings"_test = [] {
using namespace std::literals::string_view_literals;
using namespace std::literals::string_literals;
expect("str"s == "str"s);
expect("str1"s != "str2"s);
expect("str"sv == "str"sv);
expect("str1"sv != "str2"sv);
expect("str"sv == "str"s);
expect("str1"sv != "str2"s);
expect("str"s == "str"sv);
expect("str1"s != "str2"sv);
};
"types"_test = [] {
expect(type == type);
expect(type != type);
[[maybe_unused]] const auto i = 0;
expect(type == type);
expect(type != type);
};
"containers"_test = [] {
std::vector v1{1, 2, 3};
std::vector v2{1, 2, 3};
expect(v1 == v2);
expect(std::vector{"a", "b"} != std::vector{"c"});
expect(std::array{true, false} == std::array{true, false});
};
"constant"_test = [] {
constexpr auto compile_time_v = 42;
auto run_time_v = 99;
// clang-format off
expect(constant<42_i == compile_time_v> and run_time_v == 99_i);
// clang-format on
};
"convertible"_test = [] {
expect(bool(std::make_unique()));
expect(not bool(std::unique_ptr{}));
};
"boolean"_test = [] {
expect("true"_b);
expect("true"_b or not "true"_b);
expect((not "true"_b) != "true"_b);
expect("has value"_b == "value is set"_b);
};
}
boost-ext-ut-2.3.1/example/fatal.cpp 0000664 0000000 0000000 00000002642 14773232535 0017334 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
#include
int main() {
using boost::ut::operator""_test;
using namespace boost::ut::literals;
using boost::ut::fatal;
"fatal"_test = [] {
using namespace boost::ut::operators;
using boost::ut::expect;
std::optional o{42};
expect(fatal(o.has_value())) << "fatal assertion";
expect(*o == 42_i);
};
"fatal logging"_test = [] {
using namespace boost::ut::operators;
using boost::ut::expect;
std::optional o{42};
expect(fatal(o.has_value())) << "fatal assertion";
expect(*o == 42_i);
};
"fatal matcher"_test = [] {
using namespace boost::ut::operators;
using boost::ut::expect;
using boost::ut::that;
std::optional o{42};
expect(fatal(that % o.has_value()) and that % *o == 42)
<< "fatal assertion";
};
"fatal terse"_test = [] {
using namespace boost::ut::operators::terse;
std::optional o{42};
(o.has_value() >> fatal and *o == 42_i) << "fatal assertion";
};
using namespace boost::ut::operators;
using boost::ut::expect;
std::vector v{1u};
expect(fatal(std::size(v) == 1_ul)) << "fatal assertion";
expect(v[0] == 1_u);
}
boost-ext-ut-2.3.1/example/filter.cpp 0000664 0000000 0000000 00000001012 14773232535 0017520 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using namespace boost::ut;
cfg = {.filter = "run.sub1"};
"run"_test = [] {
"sub1"_test = [] { expect(42 == 42_i); };
"sub2"_test = [] { expect(43 == 42_i); };
};
"don't run"_test = [] { expect(0 == 1_i) << "don't run"; };
}
boost-ext-ut-2.3.1/example/gherkin.cpp 0000664 0000000 0000000 00000004213 14773232535 0017670 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
#include
#include
#include
template
class calculator {
public:
auto enter(const T& value) -> void { values_.push_back(value); }
auto add() -> void {
result_ = std::accumulate(std::cbegin(values_), std::cend(values_), T{});
}
auto sub() -> void {
result_ = std::accumulate(std::cbegin(values_) + 1, std::cend(values_),
values_.front(), std::minus{});
}
auto get() const -> T { return result_; }
private:
std::vector values_{};
T result_{};
};
int main(int argc, const char** argv) {
using namespace boost::ut;
bdd::gherkin::steps steps = [](auto& steps) {
steps.feature("Calculator") = [&] {
steps.scenario("*") = [&] {
steps.given("I have calculator") = [&] {
calculator calc{};
steps.when("I enter {value}") = [&](int value) { calc.enter(value); };
steps.when("I press add") = [&] { calc.add(); };
steps.when("I press sub") = [&] { calc.sub(); };
steps.then("I expect {value}") = [&](int result) {
expect(that % calc.get() == result);
};
};
};
};
};
// clang-format off
"Calculator"_test = steps |
R"(
Feature: Calculator
Scenario: Addition
Given I have calculator
When I enter 40
When I enter 2
When I press add
Then I expect 42
Scenario: Subtraction
Given I have calculator
When I enter 4
When I enter 2
When I press sub
Then I expect 2
)";
// clang-format on
if (argc == 2) {
const auto file = [](const auto path) {
std::ifstream file{path};
return std::string{(std::istreambuf_iterator(file)),
std::istreambuf_iterator()};
};
"Calculator"_test = steps | file(argv[1]);
}
}
boost-ext-ut-2.3.1/example/gherkin.feature 0000664 0000000 0000000 00000000471 14773232535 0020543 0 ustar 00root root 0000000 0000000 Feature: Calculator
Scenario: Addition
Given I have calculator
When I enter 40
When I enter 2
When I press add
Then I expect 42
Scenario: Subtraction
Given I have calculator
When I enter 45
When I enter 2
When I enter 1
When I press sub
Then I expect 42
boost-ext-ut-2.3.1/example/hello_world.cpp 0000664 0000000 0000000 00000000744 14773232535 0020560 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
constexpr auto sum = [](auto... args) { return (0 + ... + args); };
int main() {
using namespace boost::ut;
"hello world"_test = [] {
expect(0_i == sum());
expect(1_i == sum(1));
expect(3_i == sum(1, 2));
};
}
boost-ext-ut-2.3.1/example/log.cpp 0000664 0000000 0000000 00000002137 14773232535 0017025 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#ifdef __cpp_lib_expected
#include
#include
#endif
int main() {
using namespace boost::ut;
"log"_test = [] {
boost::ut::log << "pre:" << 42;
expect(42_i == 42) << "message on failure";
boost::ut::log << "post";
};
#if defined(__cpp_lib_expected)
"lazy log"_test = [] {
// It's not possible to write a test like:
// expect(e.has_value()) << e.error() << fatal;
// This would evaluate e.error() when there is no error, instead lazy
// evaluation is needed.
std::expected e = true;
expect(e.has_value()) << [&] { return e.error(); } << fatal;
expect(e.value() == true);
};
#endif
#if defined(BOOST_UT_HAS_FORMAT)
"log format"_test = [] {
boost::ut::log("\npre: {}\n", 42);
expect(42_i == 42) << "message on failure";
boost::ut::log("\npost\n");
};
#endif
}
boost-ext-ut-2.3.1/example/macro.cpp 0000664 0000000 0000000 00000002074 14773232535 0017345 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
#define EXPECT(...) \
using namespace ::boost::ut; \
::boost::ut::expect(::boost::ut::that % __VA_ARGS__)
#define SUITE ::boost::ut::suite _ = []
#define TEST(name) ::boost::ut::detail::test{"test", name} = [=]() mutable
#define TEST_P(name, ...) \
using namespace ::boost::ut::operators; \
::boost::ut::detail::test{"test", name} = [=](__VA_ARGS__) mutable
SUITE {
TEST("suite") { EXPECT(42 == 42); };
TEST_P("parameterized", const auto& arg) {
EXPECT(arg > 0) << "all values greater than 0";
}
| std::vector{1, 2, 3};
};
int main() {
TEST("macro") { EXPECT(1 != 2); };
TEST("vector") {
std::vector v(5);
EXPECT((5u == std::size(v)) >> fatal);
TEST("resize bigger") {
v.resize(10);
EXPECT(10u == std::size(v));
};
};
}
boost-ext-ut-2.3.1/example/main.cpp 0000664 0000000 0000000 00000000720 14773232535 0017164 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
auto main(int argc, const char** argv) -> int {
using namespace boost::ut;
expect((argc == 2_i) >> fatal) << "Not enough parameters!";
cfg = {.filter = argv[1]};
return cfg.run();
}
boost-ext-ut-2.3.1/example/matcher.cpp 0000664 0000000 0000000 00000004236 14773232535 0017671 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
#include
#include
#include
class matcher : public boost::ut::detail::op {
public:
matcher(bool result, const std::string& str) : result_{result}, str_{str} {}
constexpr explicit operator bool() const { return result_; }
friend auto operator<<(std::ostream& os, const matcher& self)
-> std::ostream& {
return (os << self.str_);
}
private:
const bool result_{};
const std::string str_{};
};
template
class any_of {
public:
constexpr explicit any_of(Ts... ts) : ts_{ts...} {}
constexpr auto operator==(std::common_type_t t) const {
return std::apply([t](auto... args) { return eq(t, args...); }, ts_);
}
private:
template
static constexpr auto eq(const T& t, const U& u, const TArgs&... args) {
using namespace boost::ut;
if constexpr (sizeof...(args) > 0) {
return (that % detail::value{u} == t) or eq(t, args...);
} else {
return (that % detail::value{u} == t);
}
}
std::tuple ts_;
};
int main() {
using namespace boost::ut;
using namespace std::literals::string_view_literals;
"matcher"_test = [] {
constexpr auto is_between = [](auto lhs, auto rhs) {
return [=](auto value) {
return that % value >= lhs and that % value <= rhs;
};
};
constexpr auto ends_with = [](const auto& arg, const auto& ext) {
std::stringstream str{};
str << '(' << arg << " ends with " << ext << ')';
if (ext.size() > arg.size()) {
return matcher{{}, str.str()};
}
return matcher{std::equal(ext.rbegin(), ext.rend(), arg.rbegin()),
str.str()};
};
auto value = 42;
auto str = "example.test"sv;
expect(is_between(1, 100)(value) and not is_between(1, 100)(0));
expect(ends_with(str, ".test"sv));
expect(any_of{1, 2, 3} == 2 or any_of{42, 43} == 44);
};
}
boost-ext-ut-2.3.1/example/minimal.cpp 0000664 0000000 0000000 00000000446 14773232535 0017673 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() { boost::ut::expect(true); }
boost-ext-ut-2.3.1/example/module.cpp 0000664 0000000 0000000 00000000730 14773232535 0017526 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
import boost.ut;
int main() {
using namespace boost::ut;
"module"_test = [] {
// clang-format off
expect(42_i == 42 and constant<3 == 3_i>);
// clang-format on
expect(std::vector{1, 2, 3} == std::vector{1, 2, 3});
};
}
boost-ext-ut-2.3.1/example/mut.cpp 0000664 0000000 0000000 00000001203 14773232535 0017042 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using namespace boost::ut;
auto i = 0; // mutable
"mut"_test = [i] {
expect((i == 0_i) >> fatal); // immutable
should("++") = [i] {
expect(++mut(i) == 1_i); // mutable
expect(i == 1_i); // immutable
};
should("--") = [i] {
expect(--mut(i) == -1_i); // mutable
expect(i == -1_i); // immutable
};
};
}
boost-ext-ut-2.3.1/example/parameterized.cpp 0000664 0000000 0000000 00000005735 14773232535 0021107 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
#include
#include
#include
#include
#include
#include
namespace boost::inline ext::ut {
namespace {
template
std::string format_test_parameter(const std::complex& arg,
[[maybe_unused]] const int counter) {
std::ostringstream oss;
oss << arg.real() << '+' << arg.imag() << 'i';
return oss.str();
}
} // namespace
} // namespace boost::inline ext::ut
int main() {
using namespace boost::ut;
/// Language syntax
for (auto i : std::vector{1, 2, 3}) {
test("args / " + std::to_string(i)) = [i] { // 3 tests
expect(that % i > 0); // 3 asserts
};
}
/// Alternative syntax
"args"_test = [](auto arg) {
expect(arg > 0_i) << "all values greater than 0";
} | std::vector{1, 2, 3};
/// Alternative syntax
#ifndef __EMSCRIPTEN__
"views"_test = [](auto arg) {
expect(arg > 0_i) << "all values greater than 0";
} | std::views::iota(1, 4);
#endif
/// Alternative syntax
"types"_test = []() {
expect(std::is_integral_v) << "all types are integrals";
} | std::tuple{};
/// Language syntax
std::apply(
[](TArgs... args) {
((test("args and types / " + std::to_string(args)) =
[&] {
expect((std::is_integral_v) >> fatal);
expect(42_i == static_cast(args) or args);
expect(type == type or type == type);
}),
...);
},
std::tuple{42, true});
/// Alternative syntax
"args and types"_test = [](TArg arg) {
expect((std::is_integral_v) >> fatal);
expect(42_i == static_cast(arg) or arg);
expect(type == type or type == type);
} | std::tuple{42, true};
// Modifying test names when using alternative syntax
// When using the alternative syntax, the test names are extended based on the
// test parameters (to ensure uniqueness). Here, for simple built-in types,
// the parameter value is printed, while other types are simply enumerated.
// Without the `format_test_parameter` overload above, the test names for the
// test below would be:
// "parameterized test names (42, int)"
// "parameterized test names (true, bool)"
// "parameterized test names (3rd parameter, std::complex)"
// However, since the overload for std::complex is available, the third test name becomes:
// "parameterized test names (1.5+2i, std::complex)"
"parameterized test names"_test = []([[maybe_unused]] TArg arg) {
expect(true);
} | std::tuple{42, true, std::complex{1.5, 2.0}};
}
boost-ext-ut-2.3.1/example/run.cpp 0000664 0000000 0000000 00000001107 14773232535 0017044 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
namespace ut = boost::ut;
ut::suite _ = [] {
using namespace ut;
"test suite"_test = [] {
"should be equal"_test = [] { expect(42_i == 42); };
};
};
int main(int argc, const char** argv) {
// explicitly run registered test suites and manually pass argc/argv
return ut::cfg<>.run({.argc = argc, .argv = argv});
}
boost-ext-ut-2.3.1/example/run_report.cpp 0000664 0000000 0000000 00000001133 14773232535 0020436 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
namespace ut = boost::ut;
ut::suite basic = [] {
using namespace ut;
should("equal") = [] { expect(42_i == 42); };
};
int main() {
const auto result = ut::cfg<>.run(
{.report_errors =
true}); // explicitly run registered test suites and report errors
std::cout << "After report\n";
return result;
}
boost-ext-ut-2.3.1/example/section.cpp 0000664 0000000 0000000 00000002415 14773232535 0017707 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
#include
#include
#include
int main() {
using namespace boost::ut;
"[vector]"_test = [] {
std::vector v(5);
expect((5_ul == std::size(v)) >> fatal);
should("resize bigger") = [v] { // or "resize bigger"_test
mut(v).resize(10);
expect(10_ul == std::size(v));
};
expect((5_ul == std::size(v)) >> fatal);
should("resize smaller") = [=]() mutable { // or "resize smaller"_test
v.resize(0);
expect(0_ul == std::size(v));
};
};
using namespace std::literals;
{
std::stringstream str{};
"[str1]"_test = [str{std::move(str)}] {
mut(str) << '1';
expect(str.str() == "1"sv);
};
}
// FIXME: [clang-analyzer-cplusplus.Move,-warnings-as-errors]
// Note: Object 'str' of type 'std::__1::basic_stringstream' is left in a
// valid but unspecified state after move
{
std::stringstream str{};
"[str2]"_test = [str{std::move(str)}] {
mut(str) << '2';
expect(str.str() == "2"sv);
};
}
}
boost-ext-ut-2.3.1/example/should.cpp 0000664 0000000 0000000 00000001003 14773232535 0017531 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using namespace boost::ut;
auto i = 0;
expect((i == 0_i) >> fatal);
should("return increased number for ++") = [i] { expect(++mut(i) == 1_i); };
should("return decreased number for --") = [i]() mutable {
expect(--i == -1_i);
};
}
boost-ext-ut-2.3.1/example/skip.cpp 0000664 0000000 0000000 00000001114 14773232535 0017204 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using namespace boost::ut;
// clang-format off
skip /
"don't run"_test = [] {
expect(42_i == 43) << "should not fire!";
expect(false) << "should fail!";
};
skip / test("don't run") = [] {
expect(42_i == 43) << "should not fire!";
expect(false) << "should fail!";
};
// clang-format on
}
boost-ext-ut-2.3.1/example/sl.cpp 0000664 0000000 0000000 00000002015 14773232535 0016655 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using namespace boost::ut;
#if defined(_MSC_VER) and not defined(__clang__)
// MSVC fails if the `""_i` literal operator is used inside the 'verify' lambda:
// "sl.cpp(16,37): error C3688: invalid literal suffix '_i'; literal operator or literal operator template 'operator ""_i' not found"
"sl"_test = [] {
static constexpr auto _42_i = 42_i;
auto verify = [](auto sl, auto i) {
expect(i == _42_i, sl) << "error with given source location";
};
verify(boost::ut::reflection::source_location::current(), 42_i);
};
#else
"sl"_test = [] {
auto verify = [](auto sl, auto i) {
expect(i == 42_i, sl) << "error with given source location";
};
verify(boost::ut::reflection::source_location::current(), 42_i);
};
#endif
}
boost-ext-ut-2.3.1/example/spec.cpp 0000664 0000000 0000000 00000001125 14773232535 0017172 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
constexpr auto sum = [](auto... args) { return (0 + ... + args); };
int main() {
using namespace boost::ut::operators::terse;
using namespace boost::ut::literals;
using namespace boost::ut::spec;
describe("sum") = [] {
it("should be 0") = [] { sum() == 0_i; };
it("should add all args") = [] { sum(1, 2, 3) == 6_i; };
};
}
boost-ext-ut-2.3.1/example/suite.cpp 0000664 0000000 0000000 00000001531 14773232535 0017372 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
namespace ut = boost::ut;
ut::suite errors = [] {
using namespace ut;
"exception"_test = [] {
expect(throws([] { throw 0; })) << "throws any exception";
};
"failure"_test = [] { expect(nothrow([] {})); };
};
#if not defined(__clang__) and not defined(_MSC_VER)
struct calc {
static inline ut::suite sum_suite = []() -> void {
using namespace ut;
"sum"_test = [] {
T calc{};
expect(6_i == calc.sum(1, 2, 3));
};
};
template
constexpr auto sum(TArgs... args) -> int {
return (args + ...);
}
};
#endif
int main() {}
boost-ext-ut-2.3.1/example/tag.cpp 0000664 0000000 0000000 00000001371 14773232535 0017016 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using namespace boost::ut;
cfg = {.filter = "tag", .tag = {"execute"}};
// clang-format off
tag("execute") / skip /
"tag"_test = [] {
expect(42_i == 43) << "should not fire!";
expect(false) << "should fail!";
};
tag("execute") / "tag"_test= [] {
expect(42_i == 42);
};
tag("not executed") / "tag"_test= [] {
expect(43_i == 42);
};
tag("not executed") / tag("execute") /
"tag"_test= [] {
expect(42_i == 42);
};
// clang-format on
}
boost-ext-ut-2.3.1/example/terse.cpp 0000664 0000000 0000000 00000002325 14773232535 0017365 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
constexpr auto sum = [](auto... args) { return (0 + ... + args); };
struct foo {
int a{};
bool b{};
constexpr auto operator==(const foo& other) const {
return a == other.a and b == other.b;
}
constexpr auto operator!=(const foo& other) const {
return not(*this == other);
}
friend auto& operator<<(std::ostream& os, const foo& f) {
return (os << "foo{" << f.a << ',' << f.b << '}');
}
};
int main() {
using boost::ut::operator""_test;
using namespace boost::ut::literals;
using namespace boost::ut::operators::terse;
"terse"_test = [] {
6_i == sum(1, 2, 3);
sum(1, 1) == 2_i;
(42_i == sum(40, 2)) and (0_i != sum(1) or 4_i == 3);
};
// clang-format off
"terse type"_test = [] {
foo{.a = 42, .b = true}%_t == foo{42, true};
foo{.a = 43, .b = true} != foo{42, true}%_t;
constexpr auto make_foo = [](auto... args) { return foo{args...}; };
foo{42, true} == make_foo(42, true)%_t;
};
// clang-format on
}
boost-ext-ut-2.3.1/example/test.cpp 0000664 0000000 0000000 00000000626 14773232535 0017224 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using namespace boost::ut;
"UDL syntax"_test = [] { expect(42_i == 42); };
test("function syntax") = [] { expect(42_i == 42); };
}
boost-ext-ut-2.3.1/example/tmp.cpp 0000664 0000000 0000000 00000002046 14773232535 0017043 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
template
struct list {};
int main() {
using namespace boost::ut;
static constexpr auto i = 42;
"type"_test = [] {
constexpr auto return_int = [] { return i; };
expect(type<>(i) == type);
expect(type == type<>(i));
expect(type == return_int());
expect(type != return_int());
};
"constant"_test = [] {
// clang-format off
expect(constant<42_i == i> and type == type and
type> == type>);
// clang-format on
};
#if defined(__cpp_concepts)
"compiles"_test = [] {
struct foo {
int value{};
};
struct bar {};
expect([](auto t) { return requires { t.value; }; }(foo{}));
expect(not[](auto t) { return requires { t.value; }; }(bar{}));
};
#endif
}
boost-ext-ut-2.3.1/example/using.cpp 0000664 0000000 0000000 00000001143 14773232535 0017365 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2020 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include
int main() {
using boost::ut::operator""_test;
using boost::ut::operator""_i;
"using"_test = [] {
using boost::ut::expect;
using boost::ut::eq;
expect(eq(42, 42));
using boost::ut::operator==;
expect(42_i == 42);
using boost::ut::operator and;
using boost::ut::that;
expect(that % 1 == 1 and that % 2 == 2);
};
}
boost-ext-ut-2.3.1/include/ 0000775 0000000 0000000 00000000000 14773232535 0015525 5 ustar 00root root 0000000 0000000 boost-ext-ut-2.3.1/include/boost/ 0000775 0000000 0000000 00000000000 14773232535 0016653 5 ustar 00root root 0000000 0000000 boost-ext-ut-2.3.1/include/boost/ut.cppm 0000664 0000000 0000000 00000000326 14773232535 0020165 0 ustar 00root root 0000000 0000000 module;
#if __has_include() and __has_include()
#include
#include
#endif
export module boost.ut;
export import std;
#define BOOST_UT_CXX_MODULES 1
#include "ut.hpp"
boost-ext-ut-2.3.1/include/boost/ut.hpp 0000664 0000000 0000000 00000312774 14773232535 0020032 0 ustar 00root root 0000000 0000000 //
// Copyright (c) 2019-2021 Kris Jusiak (kris at jusiak dot net)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#if defined(BOOST_UT_CXX_MODULES)
#define BOOST_UT_EXPORT export
#else
#pragma once
#define BOOST_UT_EXPORT
#endif
#if !defined(BOOST_UT_CXX_MODULES)
#include
#endif
#if defined(_MSC_VER)
#pragma push_macro("min")
#pragma push_macro("max")
#undef min
#undef max
#endif
// Before libc++ 17 had experimental support for format and it required a
// special build flag. Currently libc++ has not implemented all C++20 chrono
// improvements. Therefore doesn't define __cpp_lib_format, instead query the
// library version to detect the support status.
//
// MSVC STL and libstdc++ provide __cpp_lib_format.
#if defined(__cpp_lib_format) or \
(defined(_LIBCPP_VERSION) and _LIBCPP_VERSION >= 170000)
#define BOOST_UT_HAS_FORMAT
#endif
#if not defined(__cpp_rvalue_references)
#error "[Boost::ext].UT requires support for rvalue references";
#elif not defined(__cpp_decltype)
#error "[Boost::ext].UT requires support for decltype";
#elif not defined(__cpp_return_type_deduction)
#error "[Boost::ext].UT requires support for return type deduction";
#elif not defined(__cpp_deduction_guides)
#error "[Boost::ext].UT requires support for return deduction guides";
#elif not defined(__cpp_generic_lambdas)
#error "[Boost::ext].UT requires support for generic lambdas";
#elif not defined(__cpp_constexpr)
#error "[Boost::ext].UT requires support for constexpr";
#elif not defined(__cpp_alias_templates)
#error "[Boost::ext].UT requires support for alias templates";
#elif not defined(__cpp_variadic_templates)
#error "[Boost::ext].UT requires support for variadic templates";
#elif not defined(__cpp_fold_expressions)
#error "[Boost::ext].UT requires support for return fold expressions";
#elif not defined(__cpp_static_assert)
#error "[Boost::ext].UT requires support for static assert";
#else
#define BOOST_UT_VERSION 2'3'1
#if defined(__has_builtin) and defined(__GNUC__) and (__GNUC__ < 10) and \
not defined(__clang__)
#undef __has_builtin
#endif
#if not defined(__has_builtin)
#if defined(__GNUC__) and (__GNUC__ >= 9)
#define __has___builtin_FILE 1
#define __has___builtin_LINE 1
#endif
#define __has_builtin(...) __has_##__VA_ARGS__
#endif
#if !defined(BOOST_UT_CXX_MODULES)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if __has_include() and __has_include()
#include
#include
#endif
#if defined(__cpp_exceptions)
#include
#endif
#if __has_include()
#include
#endif
#if __has_include()
#include
#endif
#endif // cxx modules
struct unique_name_for_auto_detect_prefix_and_suffix_length_0123456789_struct_ {
};
BOOST_UT_EXPORT
namespace boost::inline ext::ut::inline v2_3_1 {
namespace utility {
template
class function;
template
class function {
public:
constexpr function() = default;
template
constexpr /*explicit(false)*/ function(T data)
: invoke_{invoke_impl},
destroy_{destroy_impl},
data_{new T{static_cast(data)}} {}
constexpr function(function&& other) noexcept
: invoke_{static_cast(other.invoke_)},
destroy_{static_cast(other.destroy_)},
data_{static_cast(other.data_)} {
other.data_ = {};
}
constexpr function(const function&) = delete;
~function() { destroy_(data_); }
constexpr function& operator=(const function&) = delete;
constexpr function& operator=(function&&) = delete;
[[nodiscard]] constexpr auto operator()(TArgs... args) -> R {
return invoke_(data_, args...);
}
[[nodiscard]] constexpr auto operator()(TArgs... args) const -> R {
return invoke_(data_, args...);
}
private:
template
[[nodiscard]] static auto invoke_impl(void* data, TArgs... args) -> R {
return (*static_cast(data))(args...);
}
template
static auto destroy_impl(void* data) -> void {
delete static_cast(data);
}
R (*invoke_)(void*, TArgs...){};
void (*destroy_)(void*){};
void* data_{};
};
[[nodiscard]] inline auto is_match(std::string_view input,
std::string_view pattern) -> bool {
if (std::empty(pattern)) {
return std::empty(input);
}
if (std::empty(input)) {
return pattern[0] == '*' ? is_match(input, pattern.substr(1)) : false;
}
if (pattern[0] != '?' and pattern[0] != '*' and pattern[0] != input[0]) {
return false;
}
if (pattern[0] == '*') {
for (decltype(std::size(input)) i = 0u; i <= std::size(input); ++i) {
if (is_match(input.substr(i), pattern.substr(1))) {
return true;
}
}
return false;
}
return is_match(input.substr(1), pattern.substr(1));
}
template
[[nodiscard]] constexpr auto match(const TPattern& pattern, const TStr& str)
-> std::vector {
std::vector groups{};
auto pi = 0u;
auto si = 0u;
const auto matcher = [&](char b, char e, char c = 0) {
const auto match = si;
while (str[si] and str[si] != b and str[si] != c) {
++si;
}
groups.emplace_back(str.substr(match, si - match));
while (pattern[pi] and pattern[pi] != e) {
++pi;
}
pi++;
};
while (pi < std::size(pattern) && si < std::size(str)) {
if (pattern[pi] == '\'' and str[si] == '\'' and pattern[pi + 1] == '{') {
++si;
matcher('\'', '}');
} else if (pattern[pi] == '{') {
matcher(' ', '}', ',');
} else if (pattern[pi] != str[si]) {
return {};
}
++pi;
++si;
}
if (si < str.size() or pi < std::size(pattern)) {
return {};
}
return groups;
}
template
[[nodiscard]] inline auto split(T input, TDelim delim) -> std::vector {
std::vector output{};
std::size_t first{};
while (first < std::size(input)) {
const auto second = input.find_first_of(delim, first);
if (first != second) {
output.emplace_back(input.substr(first, second - first));
}
if (second == T::npos) {
break;
}
first = second + 1;
}
return output;
}
constexpr auto regex_match(const char* str, const char* pattern) -> bool {
if (*pattern == '\0' && *str == '\0') {
return true;
}
if (*pattern == '\0' && *str != '\0') {
return false;
}
if (*str == '\0' && *pattern != '\0') {
return false;
}
if (*pattern == '.') {
return regex_match(str + 1, pattern + 1);
}
if (*pattern == *str) {
return regex_match(str + 1, pattern + 1);
}
return false;
}
} // namespace utility
namespace reflection {
#if defined(__cpp_lib_source_location) && !defined(_LIBCPP_APPLE_CLANG_VER)
using source_location = std::source_location;
#else
class source_location {
public:
[[nodiscard]] static constexpr auto current(
#if (__has_builtin(__builtin_FILE) and __has_builtin(__builtin_LINE))
const char* file = __builtin_FILE(), int line = __builtin_LINE()
#else
const char* file = "unknown", int line = {}
#endif
) noexcept {
source_location sl{};
sl.file_ = file;
sl.line_ = line;
return sl;
}
[[nodiscard]] constexpr auto file_name() const noexcept { return file_; }
[[nodiscard]] constexpr auto line() const noexcept { return line_; }
private:
const char* file_{"unknown"};
int line_{};
};
#endif
namespace detail {
template
[[nodiscard]] constexpr auto get_template_function_name_use_type()
-> std::string_view {
// for over compiler need over macros
#if defined(_MSC_VER) && !defined(__clang__)
return {&__FUNCSIG__[0], sizeof(__FUNCSIG__)};
#else
return {&__PRETTY_FUNCTION__[0], sizeof(__PRETTY_FUNCTION__)};
#endif
}
// decay allows you to highlight a cleaner name
template
[[nodiscard]] constexpr auto get_template_function_name_use_decay_type()
-> std::string_view {
return get_template_function_name_use_type>();
}
inline constexpr const std::string_view raw_type_name =
get_template_function_name_use_decay_type<
unique_name_for_auto_detect_prefix_and_suffix_length_0123456789_struct_>();
inline constexpr const std::size_t raw_length = raw_type_name.length();
inline constexpr const std::string_view need_name =
#if defined(_MSC_VER) and not defined(__clang__)
"struct "
"unique_name_for_auto_detect_prefix_and_suffix_length_0123456789_struct_";
#else
"unique_name_for_auto_detect_prefix_and_suffix_length_0123456789_struct_";
#endif
inline constexpr const std::size_t need_length = need_name.length();
static_assert(need_length <= raw_length,
"Auto find prefix and suffix length broken error 1");
inline constexpr const std::size_t prefix_length =
raw_type_name.find(need_name);
static_assert(prefix_length != std::string_view::npos,
"Auto find prefix and suffix length broken error 2");
static_assert(prefix_length <= raw_length,
"Auto find prefix and suffix length broken error 3");
inline constexpr const std::size_t tail_length = raw_length - prefix_length;
static_assert(need_length <= tail_length,
"Auto find prefix and suffix length broken error 4");
inline constexpr const std::size_t suffix_length = tail_length - need_length;
} // namespace detail
template
[[nodiscard]] constexpr auto type_name() -> std::string_view {
const std::string_view raw_type_name =
detail::get_template_function_name_use_type();
const std::size_t end = raw_type_name.length() - detail::suffix_length;
const std::size_t len = end - detail::prefix_length;
std::string_view result = raw_type_name.substr(detail::prefix_length, len);
return result;
}
// decay allows you to highlight a cleaner name
template
[[nodiscard]] constexpr auto decay_type_name() -> std::string_view {
const std::string_view raw_type_name =
detail::get_template_function_name_use_decay_type();
const std::size_t end = raw_type_name.length() - detail::suffix_length;
const std::size_t len = end - detail::prefix_length;
std::string_view result = raw_type_name.substr(detail::prefix_length, len);
return result;
}
} // namespace reflection
namespace math {
template
[[nodiscard]] constexpr auto abs(const T t) -> T {
return t < T{} ? -t : t;
}
template
[[nodiscard]] constexpr auto abs_diff(const T t, const U u)
-> decltype(t < u ? u - t : t - u) {
return t < u ? u - t : t - u;
}
template
[[nodiscard]] constexpr auto min_value(const T& lhs, const T& rhs) -> const T& {
return (rhs < lhs) ? rhs : lhs;
}
template
[[nodiscard]] constexpr auto pow(const T base, const TExp exp) -> T {
return exp ? T(base * pow(base, exp - TExp(1))) : T(1);
}
template
[[nodiscard]] constexpr auto num() -> T {
static_assert(
((Cs == '.' or Cs == '\'' or (Cs >= '0' and Cs <= '9')) and ...));
T result{};
for (const char c : std::array{Cs...}) {
if (c == '.') {
break;
}
if (c >= '0' and c <= '9') {
result = result * T(10) + T(c - '0');
}
}
return result;
}
template
[[nodiscard]] constexpr auto den() -> T {
constexpr const std::array cs{Cs...};
T result{};
auto i = 0u;
while (cs[i++] != '.') {
}
for (auto j = i; j < sizeof...(Cs); ++j) {
result += pow(T(10), sizeof...(Cs) - j) * T(cs[j] - '0');
}
return result;
}
template
[[nodiscard]] constexpr auto den_size() -> T {
constexpr const std::array cs{Cs...};
T i{};
while (cs[i++] != '.') {
}
return T(sizeof...(Cs)) - i + T(1);
}
template
[[nodiscard]] constexpr auto den_size(TValue value) -> T {
constexpr auto precision = TValue(1e-7);
T result{};
TValue tmp{};
do {
value *= 10;
tmp = value - T(value);
++result;
} while (tmp > precision);
return result;
}
} // namespace math
namespace type_traits {
template
struct list {};
template
struct identity {
using type = T;
};
template
struct function_traits : function_traits {};
template