Unverified Commit 4a786898 by Niels Lohmann

Merge branch 'develop' of https://github.com/nlohmann/json into string_view

parents d01a6a46 f2680359
...@@ -3,14 +3,18 @@ name: macOS ...@@ -3,14 +3,18 @@ name: macOS
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build: xcode:
runs-on: macos-10.15
runs-on: macos-latest strategy:
matrix:
xcode: [12.4, 12.3, 12.2, 12.1.1, 12.1, 12, 11.7, 11.6, 11.5, 11.4.1, 11.3.1, 11.2.1, 10.3]
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: cmake - name: cmake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON
- name: build - name: build
run: cmake --build build --parallel 10 run: cmake --build build --parallel 10
- name: test - name: test
......
...@@ -17,27 +17,6 @@ jobs: ...@@ -17,27 +17,6 @@ jobs:
- name: build - name: build
run: cmake --build build --target ci_test_clang_cxx20 run: cmake --build build --target ci_test_clang_cxx20
ci_clang_analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: install_ninja
run: |
sudo apt update
sudo apt install ninja-build
shell: bash
- name: install_clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 11
sudo apt-get install clang-tools-11
shell: bash
- name: cmake
run: cmake -S . -B build -DJSON_CI=On
- name: build
run: cmake --build build --target ci_clang_analyze
ci_test_clang: ci_test_clang:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
...@@ -69,94 +48,31 @@ jobs: ...@@ -69,94 +48,31 @@ jobs:
- name: build - name: build
run: cmake --build build --target ci_test_gcc run: cmake --build build --target ci_test_gcc
ci_test_valgrind: ci_static_analysis:
runs-on: ubuntu-latest
container: nlohmann/json-ci:latest
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -DJSON_CI=On
- name: build
run: cmake --build build --target ci_test_valgrind
ci_cppcheck:
runs-on: ubuntu-latest
container: nlohmann/json-ci:latest
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -DJSON_CI=On
- name: build
run: cmake --build build --target ci_cppcheck
ci_cpplint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -DJSON_CI=On
- name: build
run: cmake --build build --target ci_cpplint
ci_clang_tidy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: nlohmann/json-ci:latest container: nlohmann/json-ci:latest
strategy:
matrix:
target: [ci_clang_tidy, ci_cppcheck, ci_test_valgrind, ci_test_clang_sanitizer, ci_test_amalgamation, ci_clang_analyze, ci_cpplint]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: cmake - name: cmake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: build - name: build
run: cmake --build build --target ci_clang_tidy run: cmake --build build --target ${{ matrix.target }}
ci_test_amalgamation: ci_cmake_options:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: nlohmann/json-ci:latest container: nlohmann/json-ci:latest
strategy:
matrix:
target: [ci_test_diagnostics, ci_test_noexceptions, ci_test_noimplicitconversions]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: cmake - name: cmake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: build - name: build
run: cmake --build build --target ci_test_amalgamation run: cmake --build build --target ${{ matrix.target }}
ci_test_diagnostics:
runs-on: ubuntu-latest
container: nlohmann/json-ci:latest
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -DJSON_CI=On
- name: build
run: cmake --build build --target ci_test_diagnostics
ci_test_noexceptions:
runs-on: ubuntu-latest
container: nlohmann/json-ci:latest
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -DJSON_CI=On
- name: build
run: cmake --build build --target ci_test_noexceptions
ci_test_noimplicitconversions:
runs-on: ubuntu-latest
container: nlohmann/json-ci:latest
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -DJSON_CI=On
- name: build
run: cmake --build build --target ci_test_noimplicitconversions
ci_test_clang_sanitizer:
runs-on: ubuntu-latest
container: nlohmann/json-ci:latest
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -DJSON_CI=On
- name: build
run: cmake --build build --target ci_test_clang_sanitizer
ci_test_coverage: ci_test_coverage:
runs-on: ubuntu-latest runs-on: ubuntu-latest
...@@ -177,3 +93,16 @@ jobs: ...@@ -177,3 +93,16 @@ jobs:
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: /__w/json/json/build/json.info.filtered.noexcept path-to-lcov: /__w/json/json/build/json.info.filtered.noexcept
ci_test_compilers:
runs-on: ubuntu-latest
container: nlohmann/json-ci:latest
strategy:
matrix:
compiler: [g++-4.8, g++-4.9, g++-5, g++-7, g++-8, g++-9, g++-10, clang++-3.5, clang++-3.6, clang++-3.7, clang++-3.8, clang++-3.9, clang++-4.0, clang++-5.0, clang++-6.0, clang++-7, clang++-8, clang++-9, clang++-10]
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -DJSON_CI=On
- name: build
run: cmake --build build --target ci_test_compiler_${{ matrix.compiler }}
\ No newline at end of file
...@@ -3,51 +3,119 @@ name: Windows ...@@ -3,51 +3,119 @@ name: Windows
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
msvc2019: mingw:
runs-on: windows-latest runs-on: windows-latest
strategy:
matrix:
architecture: [x64, x86]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set up MinGW
uses: egor-tensin/setup-mingw@v2
with:
platform: ${{ matrix.architecture }}
- name: cmake - name: cmake
run: cmake -S . -B build -G "Visual Studio 16 2019" -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On run: cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On
- name: build - name: build
run: cmake --build build --parallel 10 run: cmake --build build --parallel 10
- name: test - name: test
run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure run: cd build ; ctest -j 10 -C Debug --output-on-failure
msvc2017:
runs-on: windows-2016
strategy:
matrix:
build_type: [Debug, Release]
architecture: [Win32, x64]
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000"
if: matrix.build_type == 'Release' && matrix.architecture == 'x64'
- name: cmake
run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On
if: matrix.build_type == 'Release' && matrix.architecture != 'x64'
- name: cmake
run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON
if: matrix.build_type == 'Debug'
- name: build
run: cmake --build build --config ${{ matrix.build_type }} --parallel 10
- name: test
run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure
msvc2017_latest:
runs-on: windows-2016
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -G "Visual Studio 15 2017" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4"
- name: build
run: cmake --build build --config Release --parallel 10
- name: test
run: cd build ; ctest -j 10 -C Release --output-on-failure
clang10: msvc2019:
runs-on: windows-latest runs-on: windows-latest
strategy:
matrix:
build_type: [Debug, Release]
architecture: [Win32, x64]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: install Clang
run: curl -fsSL -o LLVM10.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe ; 7z x LLVM10.exe -y -o"C:/Program Files/LLVM"
- name: cmake - name: cmake
run: cmake -S . -B build -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On
if: matrix.build_type == 'Release'
- name: cmake
run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON
if: matrix.build_type == 'Debug'
- name: build - name: build
run: cmake --build build --parallel 10 run: cmake --build build --config ${{ matrix.build_type }} --parallel 10
- name: test - name: test
run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure
clang-cl-10-x64: msvc2019_latest:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: cmake - name: cmake
run: cmake -S . -B build -G "Visual Studio 16 2019" -A x64 -T ClangCL -DJSON_BuildTests=On run: cmake -S . -B build -G "Visual Studio 16 2019" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4"
- name: build - name: build
run: cmake --build build --config Debug --parallel 10 run: cmake --build build --config Release --parallel 10
- name: test
run: cd build ; ctest -j 10 -C Release --output-on-failure
clang:
runs-on: windows-latest
strategy:
matrix:
version: [10, 11]
steps:
- uses: actions/checkout@v2
- name: install Clang
run: curl -fsSL -o LLVM${{ matrix.version }}.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ matrix.version }}.0.0/LLVM-${{ matrix.version }}.0.0-win64.exe ; 7z x LLVM${{ matrix.version }}.exe -y -o"C:/Program Files/LLVM"
- name: cmake
run: cmake -S . -B build -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On
- name: build
run: cmake --build build --parallel 10
- name: test - name: test
run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure
clang-cl-10-x86: clang-cl-11:
runs-on: windows-latest runs-on: windows-latest
strategy:
matrix:
architecture: [Win32, x64]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: cmake - name: cmake
run: cmake -S . -B build -G "Visual Studio 16 2019" -A Win32 -T ClangCL -DJSON_BuildTests=On run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -T ClangCL -DJSON_BuildTests=On
- name: build - name: build
run: cmake --build build --config Debug --parallel 10 run: cmake --build build --config Debug --parallel 10
- name: test - name: test
......
...@@ -46,164 +46,16 @@ matrix: ...@@ -46,164 +46,16 @@ matrix:
- os: osx - os: osx
osx_image: xcode10.2 osx_image: xcode10.2
- os: osx
osx_image: xcode11.2
- os: osx
osx_image: xcode12
# Linux / GCC # Linux / GCC
- os: linux - os: linux
compiler: gcc compiler: gcc
env: COMPILER=g++-4.8
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.8', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-4.9
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-5
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-6 env: COMPILER=g++-6
addons: addons:
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'ninja-build'] packages: ['g++-6', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-7
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-7', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-8
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-8', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-9
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-9', 'ninja-build']
- os: linux
compiler: gcc
env:
- COMPILER=g++-9
- CXX_STANDARD=17
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-9', 'ninja-build']
# Linux / Clang
- os: linux
compiler: clang
env: COMPILER=clang++-3.5
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5']
packages: ['g++-6', 'clang-3.5', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-3.6
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
packages: ['g++-6', 'clang-3.6', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-3.7
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7']
packages: ['g++-6', 'clang-3.7', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-3.8
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'clang-3.8', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-3.9
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'clang-3.9', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-4.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-4.0']
packages: ['g++-6', 'clang-4.0', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-5.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
packages: ['g++-6', 'clang-5.0', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-6.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
packages: ['g++-6', 'clang-6.0', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-7
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-7']
packages: ['g++-6', 'clang-7', 'ninja-build']
- os: linux
compiler: clang
env:
- COMPILER=clang++-7
- CXX_STANDARD=17
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-7']
packages: ['g++-7', 'clang-7', 'ninja-build']
################ ################
# build script # # build script #
################ ################
......
...@@ -1232,35 +1232,51 @@ The following compilers are currently used in continuous integration at [Travis] ...@@ -1232,35 +1232,51 @@ The following compilers are currently used in continuous integration at [Travis]
| Compiler | Operating System | CI Provider | | Compiler | Operating System | CI Provider |
|-------------------------------------------------------------------|--------------------|----------------| |-------------------------------------------------------------------|--------------------|----------------|
| Apple Clang 10.0.1 (clang-1001.0.46.4); Xcode 10.2.1 | macOS 10.14.4 | Travis | | Apple Clang 10.0.1 (clang-1001.0.46.4); Xcode 10.2.1 | macOS 10.14.4 | Travis |
| Apple Clang 11.0.0 (clang-1100.0.33.12); Xcode 11.2.1 | macOS 10.14.6 | Travis | | Apple Clang 10.0.1 (clang-1001.0.46.4); Xcode 10.3 | macOS 10.15.7 | GitHub Actions |
| Apple Clang 11.0.3 (clang-1103.0.32.59); Xcode 11.4.1 | macOS 10.15.4 | GitHub Actions | | Apple Clang 11.0.0 (clang-1100.0.33.12); Xcode 11.2.1 | macOS 10.15.7 | GitHub Actions |
| Apple Clang 12.0.0 (clang-1200.0.22.7); Xcode 11.4.1 | macOS 10.15.5 | Travis | | Apple Clang 11.0.0 (clang-1100.0.33.17); Xcode 11.3.1 | macOS 10.15.7 | GitHub Actions |
| Clang 3.5.0 (3.5.0-4ubuntu2\~trusty2) | Ubuntu 14.04.5 LTS | Travis | | Apple Clang 11.0.3 (clang-1103.0.32.59); Xcode 11.4.1 | macOS 10.15.7 | GitHub Actions |
| Clang 3.6.2 (3.6.2-svn240577-1\~exp1) | Ubuntu 14.04.5 LTS | Travis | | Apple Clang 11.0.3 (clang-1103.0.32.62); Xcode 11.5 | macOS 10.15.7 | GitHub Actions |
| Clang 3.7.1 (3.7.1-svn253571-1\~exp1) | Ubuntu 14.04.5 LTS | Travis | | Apple Clang 11.0.3 (clang-1103.0.32.62); Xcode 11.6 | macOS 10.15.7 | GitHub Actions |
| Clang 3.8.0 (3.8.0-2ubuntu3\~trusty5) | Ubuntu 14.04.5 LTS | Travis | | Apple Clang 11.0.3 (clang-1103.0.32.62); Xcode 11.7 | macOS 10.15.7 | GitHub Actions |
| Clang 3.9.1 (3.9.1-4ubuntu3\~14.04.3) | Ubuntu 14.04.5 LTS | Travis | | Apple Clang 12.0.0 (clang-1200.0.32.2); Xcode 12 | macOS 10.15.7 | GitHub Actions |
| Clang 4.0.1 (4.0.1-svn305264-1\~exp1) | Ubuntu 14.04.5 LTS | Travis | | Apple Clang 12.0.0 (clang-1200.0.32.21); Xcode 12.1 | macOS 10.15.7 | GitHub Actions |
| Clang 5.0.2 (version 5.0.2-svn328729-1\~exp1\~20180509123505.100) | Ubuntu 14.04.5 LTS | Travis | | Apple Clang 12.0.0 (clang-1200.0.32.21); Xcode 12.1.1 | macOS 10.15.7 | GitHub Actions |
| Clang 6.0.1 (6.0.1-svn334776-1\~exp1\~20190309042707.121) | Ubuntu 14.04.5 LTS | Travis | | Apple Clang 12.0.0 (clang-1200.0.32.27); Xcode 12.2 | macOS 10.15.7 | GitHub Actions |
| Clang 7.1.0 (7.1.0-svn353565-1\~exp1\~20190419134007.64) | Ubuntu 14.04.5 LTS | Travis | | Apple Clang 12.0.0 (clang-1200.0.32.28); Xcode 12.3 | macOS 10.15.7 | GitHub Actions |
| Clang 7.5.0 (Ubuntu 7.5.0-3ubuntu1\~18.04) | Ubuntu 18.04.4 LTS | Travis | | Apple Clang 12.0.0 (clang-1200.0.32.29); Xcode 12.4 | macOS 10.15.7 | GitHub Actions |
| Clang 9.0.0 (x86_64-pc-windows-msvc) | Windows-10.0.17763 | GitHub Actions | | GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions |
| Clang 10.0.0 (x86_64-pc-windows-msvc) | Windows-10.0.17763 | GitHub Actions | | GCC 4.9.3 (Ubuntu 4.9.3-13ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions |
| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu8\~14.04.2) | Ubuntu 14.04.5 LTS | Travis | | GCC 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.12) | Ubuntu 20.04.2 LTS | GitHub Actions |
| GCC 4.9.4 (Ubuntu 4.9.4-2ubuntu1\~14.04.1) | Ubuntu 14.04.5 LTS | Travis | | GCC 6.5.0 (Ubuntu 6.5.0-2ubuntu1~14.04.1) | Ubuntu 14.04.5 LTS | Travis |
| GCC 5.5.0 (Ubuntu 5.5.0-12ubuntu1\~14.04) | Ubuntu 14.04.5 LTS | Travis | | GCC 7.5.0 (Ubuntu 7.5.0-6ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions |
| GCC 6.5.0 (Ubuntu 6.5.0-2ubuntu1\~14.04.1) | Ubuntu 14.04.5 LTS | Travis | | GCC 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions |
| GCC 7.3.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-6.3.9600 | AppVeyor | | GCC 8.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions |
| GCC 7.5.0 (Ubuntu 7.5.0-3ubuntu1\~14.04.1) | Ubuntu 14.04.5 LTS | Travis | | GCC 8.4.0 (Ubuntu 8.4.0-3ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions |
| GCC 7.5.0 (Ubuntu 7.5.0-3ubuntu1\~18.04) | Ubuntu 18.04.4 LTS | GitHub Actions | | GCC 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) | Ubuntu 20.04.2 LTS | GitHub Actions |
| GCC 8.4.0 (Ubuntu 8.4.0-1ubuntu1\~14.04) | Ubuntu 14.04.5 LTS | Travis | | GCC 10.2.0 (Ubuntu 10.2.0-5ubuntu1~20.04) | Ubuntu 20.04.2 LTS | GitHub Actions |
| GCC 9.3.0 (Ubuntu 9.3.0-11ubuntu0\~14.04) | Ubuntu 14.04.5 LTS | Travis | | GCC 11.0.1 20210321 (experimental) | Ubuntu 20.04.2 LTS | GitHub Actions |
| MSVC 19.0.24241.7 (Build Engine version 14.0.25420.1) | Windows-6.3.9600 | AppVeyor | | Clang 3.5.2 (3.5.2-3ubuntu1) | Ubuntu 20.04.2 LTS | GitHub Actions |
| MSVC 19.16.27035.0 (15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | AppVeyor | | Clang 3.6.2 (3.6.2-3ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions |
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) | Windows-10.0.17763 | AppVeyor | | Clang 3.7.1 (3.7.1-2ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions |
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) | Windows-10.0.17763 | GitHub Actions | | Clang 3.8.0 (3.8.0-2ubuntu4) | Ubuntu 20.04.2 LTS | GitHub Actions |
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) with ClangCL 10.0.0 | Windows-10.0.17763 | GitHub Actions | | Clang 3.9.1 (3.9.1-4ubuntu3\~16.04.2) | Ubuntu 20.04.2 LTS | GitHub Actions |
| Clang 4.0.0 (4.0.0-1ubuntu1\~16.04.2) | Ubuntu 20.04.2 LTS | GitHub Actions |
| Clang 5.0.0 (5.0.0-3\~16.04.1) | Ubuntu 20.04.2 LTS | GitHub Actions |
| Clang 6.0.1 (6.0.1-14) | Ubuntu 20.04.2 LTS | GitHub Actions |
| Clang 7.0.1 (7.0.1-12) | Ubuntu 20.04.2 LTS | GitHub Actions |
| Clang 8.0.1 (8.0.1-9) | Ubuntu 20.04.2 LTS | GitHub Actions |
| Clang 9.0.1 (9.0.1-12) | Ubuntu 20.04.2 LTS | GitHub Actions |
| Clang 10.0.0 (10.0.0-4ubuntu1) | Ubuntu 20.04.2 LTS | GitHub Actions |
| Clang 10.0.0 with GNU-like command-line | Windows-10.0.17763 | GitHub Actions |
| Clang 11.0.0 with GNU-like command-line | Windows-10.0.17763 | GitHub Actions |
| Clang 11.0.0 with MSVC-like command-line | Windows-10.0.17763 | GitHub Actions |
| Clang 11.1.0 (11.1.0-++20210204121720+1fdec59bffc1-1~exp1~20210203232336.162 | Ubuntu 20.04.2 LTS | GitHub Actions |
| Visual Studio 14 2015 MSVC 19.0.24241.7 (Build Engine version 14.0.25420.1) | Windows-6.3.9600 | AppVeyor |
| Visual Studio 15 2017 MSVC 19.16.27035.0 (Build Engine version 15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | AppVeyor |
| Visual Studio 15 2017 MSVC 19.16.27045.0 (Build Engine version 15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | GitHub Actions |
| Visual Studio 16 2019 MSVC 19.28.29912.0 (Build Engine version 16.9.0+57a23d249 for .NET Framework) | Windows-10.0.17763 | GitHub Actions |
| Visual Studio 16 2019 MSVC 19.28.29912.0 (Build Engine version 16.9.0+57a23d249 for .NET Framework) | Windows-10.0.17763 | AppVeyor |
## License ## License
......
...@@ -10,48 +10,6 @@ environment: ...@@ -10,48 +10,6 @@ environment:
CMAKE_OPTIONS: "" CMAKE_OPTIONS: ""
GENERATOR: Visual Studio 14 2015 GENERATOR: Visual Studio 14 2015
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
configuration: Debug
platform: x86
CXX_FLAGS: ""
LINKER_FLAGS: ""
CMAKE_OPTIONS: ""
GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
configuration: Debug
platform: x86
CXX_FLAGS: ""
LINKER_FLAGS: ""
CMAKE_OPTIONS: ""
GENERATOR: Visual Studio 16 2019
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
configuration: Debug
platform: x64
CXX_FLAGS: ""
LINKER_FLAGS: ""
CMAKE_OPTIONS: ""
GENERATOR: Visual Studio 16 2019
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
configuration: Debug
COMPILER: mingw
platform: x86
CXX_FLAGS: ""
LINKER_FLAGS: ""
CMAKE_OPTIONS: ""
GENERATOR: Ninja
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
configuration: Release
COMPILER: mingw
platform: x86
CXX_FLAGS: ""
LINKER_FLAGS: ""
CMAKE_OPTIONS: ""
GENERATOR: Ninja
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
configuration: Release configuration: Release
platform: x86 platform: x86
...@@ -85,14 +43,6 @@ environment: ...@@ -85,14 +43,6 @@ environment:
CMAKE_OPTIONS: "-DJSON_ImplicitConversions=OFF" CMAKE_OPTIONS: "-DJSON_ImplicitConversions=OFF"
GENERATOR: Visual Studio 16 2019 GENERATOR: Visual Studio 16 2019
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
configuration: Release
platform: x64
CXX_FLAGS: ""
LINKER_FLAGS: ""
CMAKE_OPTIONS: ""
GENERATOR: Visual Studio 16 2019
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
configuration: Release configuration: Release
platform: x64 platform: x64
...@@ -109,31 +59,18 @@ environment: ...@@ -109,31 +59,18 @@ environment:
CMAKE_OPTIONS: "" CMAKE_OPTIONS: ""
GENERATOR: Visual Studio 15 2017 GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
configuration: Release
platform: x64
CXX_FLAGS: ""
LINKER_FLAGS: ""
CMAKE_OPTIONS: ""
GENERATOR: Visual Studio 16 2019
init: init:
- cmake --version - cmake --version
- msbuild /version - msbuild /version
install: install:
- if "%COMPILER%"=="mingw" appveyor DownloadFile https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip -FileName ninja.zip
- if "%COMPILER%"=="mingw" 7z x ninja.zip -oC:\projects\deps\ninja > nul
- if "%COMPILER%"=="mingw" set PATH=C:\projects\deps\ninja;%PATH%
- if "%COMPILER%"=="mingw" set PATH=C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64\bin;%PATH%
- if "%COMPILER%"=="mingw" g++ --version
- if "%platform%"=="x86" set GENERATOR_PLATFORM=Win32 - if "%platform%"=="x86" set GENERATOR_PLATFORM=Win32
before_build: before_build:
# for with_win_header build, inject the inclusion of Windows.h to the single-header library # for with_win_header build, inject the inclusion of Windows.h to the single-header library
- ps: if ($env:name -Eq "with_win_header") { $header_path = "single_include\nlohmann\json.hpp" } - ps: if ($env:name -Eq "with_win_header") { $header_path = "single_include\nlohmann\json.hpp" }
- ps: if ($env:name -Eq "with_win_header") { "#include <Windows.h>`n" + (Get-Content $header_path | Out-String) | Set-Content $header_path } - ps: if ($env:name -Eq "with_win_header") { "#include <Windows.h>`n" + (Get-Content $header_path | Out-String) | Set-Content $header_path }
- if "%GENERATOR%"=="Ninja" (cmake . -G "%GENERATOR%" -DCMAKE_BUILD_TYPE="%configuration%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%") else (cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%") - cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%"
build_script: build_script:
- cmake --build . --config "%configuration%" - cmake --build . --config "%configuration%"
......
...@@ -30,7 +30,7 @@ execute_process(COMMAND ${CPPCHECK_TOOL} --version OUTPUT_VARIABLE CPPCHECK_TOOL ...@@ -30,7 +30,7 @@ execute_process(COMMAND ${CPPCHECK_TOOL} --version OUTPUT_VARIABLE CPPCHECK_TOOL
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CPPCHECK_TOOL_VERSION "${CPPCHECK_TOOL_VERSION}") string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CPPCHECK_TOOL_VERSION "${CPPCHECK_TOOL_VERSION}")
message(STATUS "🔖 Cppcheck ${CPPCHECK_TOOL_VERSION} (${CPPCHECK_TOOL})") message(STATUS "🔖 Cppcheck ${CPPCHECK_TOOL_VERSION} (${CPPCHECK_TOOL})")
find_program(GCC_TOOL NAMES g++-HEAD g++-11 g++-10 g++) find_program(GCC_TOOL NAMES g++-HEAD g++-11 g++-latest)
execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION) execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}") string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}")
message(STATUS "🔖 GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})") message(STATUS "🔖 GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})")
...@@ -85,7 +85,7 @@ find_program(SCAN_BUILD_TOOL NAMES scan-build-11 scan-build) ...@@ -85,7 +85,7 @@ find_program(SCAN_BUILD_TOOL NAMES scan-build-11 scan-build)
file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp) file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp)
############################################################################### ###############################################################################
# Different C++ Standards. # Thorough check with recent compilers
############################################################################### ###############################################################################
set(CLANG_CXXFLAGS "-std=c++11 \ set(CLANG_CXXFLAGS "-std=c++11 \
...@@ -785,6 +785,26 @@ add_custom_target(ci_cmake_flags ...@@ -785,6 +785,26 @@ add_custom_target(ci_cmake_flags
) )
############################################################################### ###############################################################################
# Use more installed compilers.
###############################################################################
foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-7 g++-8 g++-9 g++-10 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11)
find_program(COMPILER_TOOL NAMES ${COMPILER})
if (COMPILER_TOOL)
add_custom_target(ci_test_compiler_${COMPILER}
COMMAND CXX=${COMPILER} ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja
-DJSON_BuildTests=ON -DJSON_FastTests=ON
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure
COMMENT "Compile and test with ${COMPILER}"
)
endif()
unset(COMPILER_TOOL CACHE)
endforeach()
###############################################################################
# Clean up all generated files. # Clean up all generated files.
############################################################################### ###############################################################################
......
...@@ -2,6 +2,7 @@ option(JSON_Sanitizer "Build test suite with Clang sanitizer" OFF) ...@@ -2,6 +2,7 @@ option(JSON_Sanitizer "Build test suite with Clang sanitizer" OFF)
option(JSON_Valgrind "Execute test suite with Valgrind" OFF) option(JSON_Valgrind "Execute test suite with Valgrind" OFF)
option(JSON_NoExceptions "Build test suite without exceptions" OFF) option(JSON_NoExceptions "Build test suite without exceptions" OFF)
option(JSON_Coverage "Build test suite with coverage information" OFF) option(JSON_Coverage "Build test suite with coverage information" OFF)
option(JSON_FastTests "Whether to skip expensive tests" OFF)
# download test data # download test data
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/download_test_data.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/download_test_data.cmake)
...@@ -112,10 +113,17 @@ foreach(file ${files}) ...@@ -112,10 +113,17 @@ foreach(file ${files})
target_link_libraries(${testcase} PRIVATE --coverage) target_link_libraries(${testcase} PRIVATE --coverage)
endif() endif()
if (JSON_FastTests)
add_test(NAME "${testcase}"
COMMAND ${testcase} ${DOCTEST_TEST_FILTER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
else()
add_test(NAME "${testcase}" add_test(NAME "${testcase}"
COMMAND ${testcase} ${DOCTEST_TEST_FILTER} --no-skip COMMAND ${testcase} ${DOCTEST_TEST_FILTER} --no-skip
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
) )
endif()
set_tests_properties("${testcase}" PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA) set_tests_properties("${testcase}" PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA)
if(JSON_Valgrind) if(JSON_Valgrind)
......
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2016-2020 Viktor Kirilov Copyright (c) 2016-2021 Viktor Kirilov
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
// //
// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD // doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
// //
// Copyright (c) 2016-2020 Viktor Kirilov // Copyright (c) 2016-2021 Viktor Kirilov
// //
// Distributed under the MIT Software License // Distributed under the MIT Software License
// See accompanying file LICENSE.txt or copy at // See accompanying file LICENSE.txt or copy at
...@@ -48,8 +48,8 @@ ...@@ -48,8 +48,8 @@
#define DOCTEST_VERSION_MAJOR 2 #define DOCTEST_VERSION_MAJOR 2
#define DOCTEST_VERSION_MINOR 4 #define DOCTEST_VERSION_MINOR 4
#define DOCTEST_VERSION_PATCH 4 #define DOCTEST_VERSION_PATCH 6
#define DOCTEST_VERSION_STR "2.4.4" #define DOCTEST_VERSION_STR "2.4.6"
#define DOCTEST_VERSION \ #define DOCTEST_VERSION \
(DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
...@@ -354,7 +354,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' ...@@ -354,7 +354,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
#define DOCTEST_GLOBAL_NO_WARNINGS(var) \ #define DOCTEST_GLOBAL_NO_WARNINGS(var) \
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-variable") \ DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-variable") \
static int var DOCTEST_UNUSED // NOLINT(fuchsia-statically-constructed-objects,cert-err58-cpp) static const int var DOCTEST_UNUSED // NOLINT(fuchsia-statically-constructed-objects,cert-err58-cpp)
#define DOCTEST_GLOBAL_NO_WARNINGS_END() DOCTEST_CLANG_SUPPRESS_WARNING_POP #define DOCTEST_GLOBAL_NO_WARNINGS_END() DOCTEST_CLANG_SUPPRESS_WARNING_POP
#ifndef DOCTEST_BREAK_INTO_DEBUGGER #ifndef DOCTEST_BREAK_INTO_DEBUGGER
...@@ -362,16 +362,16 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' ...@@ -362,16 +362,16 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
#ifdef DOCTEST_PLATFORM_LINUX #ifdef DOCTEST_PLATFORM_LINUX
#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
// Break at the location of the failing check if possible // Break at the location of the failing check if possible
#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT (hicpp-no-assembler)
#else #else
#include <signal.h> #include <signal.h>
#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP) #define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP)
#endif #endif
#elif defined(DOCTEST_PLATFORM_MAC) #elif defined(DOCTEST_PLATFORM_MAC)
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386) #if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386)
#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT (hicpp-no-assembler)
#else #else
#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT (hicpp-no-assembler)
#endif #endif
#elif DOCTEST_MSVC #elif DOCTEST_MSVC
#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() #define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
...@@ -656,12 +656,14 @@ DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file); ...@@ -656,12 +656,14 @@ DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file);
struct DOCTEST_INTERFACE TestCaseData struct DOCTEST_INTERFACE TestCaseData
{ {
String m_file; // the file in which the test was registered String m_file; // the file in which the test was registered (using String - see #350)
unsigned m_line; // the line where the test was registered unsigned m_line; // the line where the test was registered
const char* m_name; // name of the test case const char* m_name; // name of the test case
const char* m_test_suite; // the test suite in which the test was added const char* m_test_suite; // the test suite in which the test was added
const char* m_description; const char* m_description;
bool m_skip; bool m_skip;
bool m_no_breaks;
bool m_no_output;
bool m_may_fail; bool m_may_fail;
bool m_should_fail; bool m_should_fail;
int m_expected_failures; int m_expected_failures;
...@@ -715,12 +717,18 @@ struct DOCTEST_INTERFACE IContextScope ...@@ -715,12 +717,18 @@ struct DOCTEST_INTERFACE IContextScope
virtual void stringify(std::ostream*) const = 0; virtual void stringify(std::ostream*) const = 0;
}; };
namespace detail {
struct DOCTEST_INTERFACE TestCase;
} // namespace detail
struct ContextOptions //!OCLINT too many fields struct ContextOptions //!OCLINT too many fields
{ {
std::ostream* cout; // stdout stream - std::cout by default std::ostream* cout; // stdout stream - std::cout by default
std::ostream* cerr; // stderr stream - std::cerr by default std::ostream* cerr; // stderr stream - std::cerr by default
String binary_name; // the test binary name String binary_name; // the test binary name
const detail::TestCase* currentTest = nullptr;
// == parameters from the command line // == parameters from the command line
String out; // output filename String out; // output filename
String order_by; // how tests should be ordered String order_by; // how tests should be ordered
...@@ -773,6 +781,29 @@ namespace detail { ...@@ -773,6 +781,29 @@ namespace detail {
template<class T> struct remove_reference<T&> { typedef T type; }; template<class T> struct remove_reference<T&> { typedef T type; };
template<class T> struct remove_reference<T&&> { typedef T type; }; template<class T> struct remove_reference<T&&> { typedef T type; };
template<typename T, typename U = T&&> U declval(int);
template<typename T> T declval(long);
template<typename T> auto declval() DOCTEST_NOEXCEPT -> decltype(declval<T>(0)) ;
template<class T> struct is_lvalue_reference { const static bool value=false; };
template<class T> struct is_lvalue_reference<T&> { const static bool value=true; };
template <class T>
inline T&& forward(typename remove_reference<T>::type& t) DOCTEST_NOEXCEPT
{
return static_cast<T&&>(t);
}
template <class T>
inline T&& forward(typename remove_reference<T>::type&& t) DOCTEST_NOEXCEPT
{
static_assert(!is_lvalue_reference<T>::value,
"Can not forward an rvalue as an lvalue.");
return static_cast<T&&>(t);
}
template<class T> struct remove_const { typedef T type; }; template<class T> struct remove_const { typedef T type; };
template<class T> struct remove_const<const T> { typedef T type; }; template<class T> struct remove_const<const T> { typedef T type; };
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
...@@ -1040,10 +1071,20 @@ namespace detail { ...@@ -1040,10 +1071,20 @@ namespace detail {
return toString(lhs) + op + toString(rhs); return toString(lhs) + op + toString(rhs);
} }
#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
#endif
// This will check if there is any way it could find a operator like member or friend and uses it.
// If not it doesn't find the operator or if the operator at global scope is defined after
// this template, the template won't be instantiated due to SFINAE. Once the template is not
// instantiated it can look for global operator using normal conversions.
#define SFINAE_OP(ret,op) decltype(doctest::detail::declval<L>() op doctest::detail::declval<R>(),static_cast<ret>(0))
#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ #define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \
template <typename R> \ template <typename R> \
DOCTEST_NOINLINE Result operator op(const DOCTEST_REF_WRAP(R) rhs) { \ DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \
bool res = op_macro(lhs, rhs); \ bool res = op_macro(doctest::detail::forward<L>(lhs), doctest::detail::forward<R>(rhs)); \
if(m_at & assertType::is_false) \ if(m_at & assertType::is_false) \
res = !res; \ res = !res; \
if(!res || doctest::getContextOptions()->success) \ if(!res || doctest::getContextOptions()->success) \
...@@ -1171,12 +1212,16 @@ namespace detail { ...@@ -1171,12 +1212,16 @@ namespace detail {
L lhs; L lhs;
assertType::Enum m_at; assertType::Enum m_at;
explicit Expression_lhs(L in, assertType::Enum at) explicit Expression_lhs(L&& in, assertType::Enum at)
: lhs(in) : lhs(doctest::detail::forward<L>(in))
, m_at(at) {} , m_at(at) {}
DOCTEST_NOINLINE operator Result() { DOCTEST_NOINLINE operator Result() {
bool res = !!lhs; // this is needed only foc MSVC 2015:
// https://ci.appveyor.com/project/onqtam/doctest/builds/38181202
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool
bool res = static_cast<bool>(lhs);
DOCTEST_MSVC_SUPPRESS_WARNING_POP
if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional
res = !res; res = !res;
...@@ -1185,6 +1230,10 @@ namespace detail { ...@@ -1185,6 +1230,10 @@ namespace detail {
return Result(res); return Result(res);
} }
/* This is required for user-defined conversions from Expression_lhs to L */
//operator L() const { return lhs; }
operator L() const { return lhs; }
// clang-format off // clang-format off
DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
...@@ -1225,6 +1274,10 @@ namespace detail { ...@@ -1225,6 +1274,10 @@ namespace detail {
#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
DOCTEST_CLANG_SUPPRESS_WARNING_POP
#endif
struct DOCTEST_INTERFACE ExpressionDecomposer struct DOCTEST_INTERFACE ExpressionDecomposer
{ {
assertType::Enum m_at; assertType::Enum m_at;
...@@ -1236,8 +1289,8 @@ namespace detail { ...@@ -1236,8 +1289,8 @@ namespace detail {
// https://github.com/catchorg/Catch2/issues/870 // https://github.com/catchorg/Catch2/issues/870
// https://github.com/catchorg/Catch2/issues/565 // https://github.com/catchorg/Catch2/issues/565
template <typename L> template <typename L>
Expression_lhs<const DOCTEST_REF_WRAP(L)> operator<<(const DOCTEST_REF_WRAP(L) operand) { Expression_lhs<L> operator<<(L &&operand) {
return Expression_lhs<const DOCTEST_REF_WRAP(L)>(operand, m_at); return Expression_lhs<L>(doctest::detail::forward<L>(operand), m_at);
} }
}; };
...@@ -1246,6 +1299,8 @@ namespace detail { ...@@ -1246,6 +1299,8 @@ namespace detail {
const char* m_test_suite; const char* m_test_suite;
const char* m_description; const char* m_description;
bool m_skip; bool m_skip;
bool m_no_breaks;
bool m_no_output;
bool m_may_fail; bool m_may_fail;
bool m_should_fail; bool m_should_fail;
int m_expected_failures; int m_expected_failures;
...@@ -1524,7 +1579,7 @@ namespace detail { ...@@ -1524,7 +1579,7 @@ namespace detail {
template <typename L> class ContextScope : public ContextScopeBase template <typename L> class ContextScope : public ContextScopeBase
{ {
const L &lambda_; const L lambda_;
public: public:
explicit ContextScope(const L &lambda) : lambda_(lambda) {} explicit ContextScope(const L &lambda) : lambda_(lambda) {}
...@@ -1585,6 +1640,8 @@ namespace detail { ...@@ -1585,6 +1640,8 @@ namespace detail {
DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); DOCTEST_DEFINE_DECORATOR(test_suite, const char*, "");
DOCTEST_DEFINE_DECORATOR(description, const char*, ""); DOCTEST_DEFINE_DECORATOR(description, const char*, "");
DOCTEST_DEFINE_DECORATOR(skip, bool, true); DOCTEST_DEFINE_DECORATOR(skip, bool, true);
DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true);
DOCTEST_DEFINE_DECORATOR(no_output, bool, true);
DOCTEST_DEFINE_DECORATOR(timeout, double, 0); DOCTEST_DEFINE_DECORATOR(timeout, double, 0);
DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); DOCTEST_DEFINE_DECORATOR(may_fail, bool, true);
DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); DOCTEST_DEFINE_DECORATOR(should_fail, bool, true);
...@@ -1921,10 +1978,12 @@ int registerReporter(const char* name, int priority, bool isReporter) { ...@@ -1921,10 +1978,12 @@ int registerReporter(const char* name, int priority, bool isReporter) {
static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() { \ static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() { \
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \
static doctest::detail::TestSuite data; \ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \
static doctest::detail::TestSuite data{}; \
static bool inited = false; \ static bool inited = false; \
DOCTEST_MSVC_SUPPRESS_WARNING_POP \ DOCTEST_MSVC_SUPPRESS_WARNING_POP \
DOCTEST_CLANG_SUPPRESS_WARNING_POP \ DOCTEST_CLANG_SUPPRESS_WARNING_POP \
DOCTEST_GCC_SUPPRESS_WARNING_POP \
if(!inited) { \ if(!inited) { \
data* decorators; \ data* decorators; \
inited = true; \ inited = true; \
...@@ -1979,17 +2038,15 @@ int registerReporter(const char* name, int priority, bool isReporter) { ...@@ -1979,17 +2038,15 @@ int registerReporter(const char* name, int priority, bool isReporter) {
// for logging // for logging
#define DOCTEST_INFO(...) \ #define DOCTEST_INFO(...) \
DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \ DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \
DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), __VA_ARGS__) __VA_ARGS__)
#define DOCTEST_INFO_IMPL(lambda_name, mb_name, s_name, ...) \ #define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4626) \ auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \
auto lambda_name = [&](std::ostream* s_name) { \ [&](std::ostream* s_name) { \
doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \
mb_name.m_stream = s_name; \ mb_name.m_stream = s_name; \
mb_name * __VA_ARGS__; \ mb_name * __VA_ARGS__; \
}; \ })
DOCTEST_MSVC_SUPPRESS_WARNING_POP \
auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope(lambda_name)
#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) #define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x)
...@@ -2461,7 +2518,7 @@ int registerReporter(const char* name, int priority, bool isReporter) { ...@@ -2461,7 +2518,7 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE #define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE
#define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE #define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE
#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE DOCTEST_TEST_CASE_TEMPLATE_INVOKE #define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__)
// clang-format on // clang-format on
// BDD style macros // BDD style macros
...@@ -2481,138 +2538,138 @@ int registerReporter(const char* name, int priority, bool isReporter) { ...@@ -2481,138 +2538,138 @@ int registerReporter(const char* name, int priority, bool isReporter) {
// == SHORT VERSIONS OF THE MACROS // == SHORT VERSIONS OF THE MACROS
#if !defined(DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES) #if !defined(DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES)
#define TEST_CASE DOCTEST_TEST_CASE #define TEST_CASE(name) DOCTEST_TEST_CASE(name)
#define TEST_CASE_CLASS DOCTEST_TEST_CASE_CLASS #define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name)
#define TEST_CASE_FIXTURE DOCTEST_TEST_CASE_FIXTURE #define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name)
#define TYPE_TO_STRING DOCTEST_TYPE_TO_STRING #define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__)
#define TEST_CASE_TEMPLATE DOCTEST_TEST_CASE_TEMPLATE #define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__)
#define TEST_CASE_TEMPLATE_DEFINE DOCTEST_TEST_CASE_TEMPLATE_DEFINE #define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id)
#define TEST_CASE_TEMPLATE_INVOKE DOCTEST_TEST_CASE_TEMPLATE_INVOKE #define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__)
#define TEST_CASE_TEMPLATE_APPLY DOCTEST_TEST_CASE_TEMPLATE_APPLY #define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__)
#define SUBCASE DOCTEST_SUBCASE #define SUBCASE(name) DOCTEST_SUBCASE(name)
#define TEST_SUITE DOCTEST_TEST_SUITE #define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators)
#define TEST_SUITE_BEGIN DOCTEST_TEST_SUITE_BEGIN #define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name)
#define TEST_SUITE_END DOCTEST_TEST_SUITE_END #define TEST_SUITE_END DOCTEST_TEST_SUITE_END
#define REGISTER_EXCEPTION_TRANSLATOR DOCTEST_REGISTER_EXCEPTION_TRANSLATOR #define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature)
#define REGISTER_REPORTER DOCTEST_REGISTER_REPORTER #define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter)
#define REGISTER_LISTENER DOCTEST_REGISTER_LISTENER #define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter)
#define INFO DOCTEST_INFO #define INFO(...) DOCTEST_INFO(__VA_ARGS__)
#define CAPTURE DOCTEST_CAPTURE #define CAPTURE(x) DOCTEST_CAPTURE(x)
#define ADD_MESSAGE_AT DOCTEST_ADD_MESSAGE_AT #define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__)
#define ADD_FAIL_CHECK_AT DOCTEST_ADD_FAIL_CHECK_AT #define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__)
#define ADD_FAIL_AT DOCTEST_ADD_FAIL_AT #define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__)
#define MESSAGE DOCTEST_MESSAGE #define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__)
#define FAIL_CHECK DOCTEST_FAIL_CHECK #define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__)
#define FAIL DOCTEST_FAIL #define FAIL(...) DOCTEST_FAIL(__VA_ARGS__)
#define TO_LVALUE DOCTEST_TO_LVALUE #define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__)
#define WARN DOCTEST_WARN #define WARN(...) DOCTEST_WARN(__VA_ARGS__)
#define WARN_FALSE DOCTEST_WARN_FALSE #define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__)
#define WARN_THROWS DOCTEST_WARN_THROWS #define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__)
#define WARN_THROWS_AS DOCTEST_WARN_THROWS_AS #define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__)
#define WARN_THROWS_WITH DOCTEST_WARN_THROWS_WITH #define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__)
#define WARN_THROWS_WITH_AS DOCTEST_WARN_THROWS_WITH_AS #define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__)
#define WARN_NOTHROW DOCTEST_WARN_NOTHROW #define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__)
#define CHECK DOCTEST_CHECK #define CHECK(...) DOCTEST_CHECK(__VA_ARGS__)
#define CHECK_FALSE DOCTEST_CHECK_FALSE #define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__)
#define CHECK_THROWS DOCTEST_CHECK_THROWS #define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__)
#define CHECK_THROWS_AS DOCTEST_CHECK_THROWS_AS #define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__)
#define CHECK_THROWS_WITH DOCTEST_CHECK_THROWS_WITH #define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__)
#define CHECK_THROWS_WITH_AS DOCTEST_CHECK_THROWS_WITH_AS #define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__)
#define CHECK_NOTHROW DOCTEST_CHECK_NOTHROW #define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__)
#define REQUIRE DOCTEST_REQUIRE #define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__)
#define REQUIRE_FALSE DOCTEST_REQUIRE_FALSE #define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__)
#define REQUIRE_THROWS DOCTEST_REQUIRE_THROWS #define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__)
#define REQUIRE_THROWS_AS DOCTEST_REQUIRE_THROWS_AS #define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__)
#define REQUIRE_THROWS_WITH DOCTEST_REQUIRE_THROWS_WITH #define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__)
#define REQUIRE_THROWS_WITH_AS DOCTEST_REQUIRE_THROWS_WITH_AS #define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__)
#define REQUIRE_NOTHROW DOCTEST_REQUIRE_NOTHROW #define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__)
#define WARN_MESSAGE DOCTEST_WARN_MESSAGE #define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__)
#define WARN_FALSE_MESSAGE DOCTEST_WARN_FALSE_MESSAGE #define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__)
#define WARN_THROWS_MESSAGE DOCTEST_WARN_THROWS_MESSAGE #define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__)
#define WARN_THROWS_AS_MESSAGE DOCTEST_WARN_THROWS_AS_MESSAGE #define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
#define WARN_THROWS_WITH_MESSAGE DOCTEST_WARN_THROWS_WITH_MESSAGE #define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
#define WARN_THROWS_WITH_AS_MESSAGE DOCTEST_WARN_THROWS_WITH_AS_MESSAGE #define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
#define WARN_NOTHROW_MESSAGE DOCTEST_WARN_NOTHROW_MESSAGE #define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__)
#define CHECK_MESSAGE DOCTEST_CHECK_MESSAGE #define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__)
#define CHECK_FALSE_MESSAGE DOCTEST_CHECK_FALSE_MESSAGE #define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__)
#define CHECK_THROWS_MESSAGE DOCTEST_CHECK_THROWS_MESSAGE #define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__)
#define CHECK_THROWS_AS_MESSAGE DOCTEST_CHECK_THROWS_AS_MESSAGE #define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
#define CHECK_THROWS_WITH_MESSAGE DOCTEST_CHECK_THROWS_WITH_MESSAGE #define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
#define CHECK_THROWS_WITH_AS_MESSAGE DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE #define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
#define CHECK_NOTHROW_MESSAGE DOCTEST_CHECK_NOTHROW_MESSAGE #define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__)
#define REQUIRE_MESSAGE DOCTEST_REQUIRE_MESSAGE #define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__)
#define REQUIRE_FALSE_MESSAGE DOCTEST_REQUIRE_FALSE_MESSAGE #define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__)
#define REQUIRE_THROWS_MESSAGE DOCTEST_REQUIRE_THROWS_MESSAGE #define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__)
#define REQUIRE_THROWS_AS_MESSAGE DOCTEST_REQUIRE_THROWS_AS_MESSAGE #define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
#define REQUIRE_THROWS_WITH_MESSAGE DOCTEST_REQUIRE_THROWS_WITH_MESSAGE #define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
#define REQUIRE_THROWS_WITH_AS_MESSAGE DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE #define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
#define REQUIRE_NOTHROW_MESSAGE DOCTEST_REQUIRE_NOTHROW_MESSAGE #define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__)
#define SCENARIO DOCTEST_SCENARIO #define SCENARIO(name) DOCTEST_SCENARIO(name)
#define SCENARIO_CLASS DOCTEST_SCENARIO_CLASS #define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name)
#define SCENARIO_TEMPLATE DOCTEST_SCENARIO_TEMPLATE #define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__)
#define SCENARIO_TEMPLATE_DEFINE DOCTEST_SCENARIO_TEMPLATE_DEFINE #define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id)
#define GIVEN DOCTEST_GIVEN #define GIVEN(name) DOCTEST_GIVEN(name)
#define WHEN DOCTEST_WHEN #define WHEN(name) DOCTEST_WHEN(name)
#define AND_WHEN DOCTEST_AND_WHEN #define AND_WHEN(name) DOCTEST_AND_WHEN(name)
#define THEN DOCTEST_THEN #define THEN(name) DOCTEST_THEN(name)
#define AND_THEN DOCTEST_AND_THEN #define AND_THEN(name) DOCTEST_AND_THEN(name)
#define WARN_EQ DOCTEST_WARN_EQ #define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__)
#define CHECK_EQ DOCTEST_CHECK_EQ #define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__)
#define REQUIRE_EQ DOCTEST_REQUIRE_EQ #define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__)
#define WARN_NE DOCTEST_WARN_NE #define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__)
#define CHECK_NE DOCTEST_CHECK_NE #define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__)
#define REQUIRE_NE DOCTEST_REQUIRE_NE #define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__)
#define WARN_GT DOCTEST_WARN_GT #define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__)
#define CHECK_GT DOCTEST_CHECK_GT #define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__)
#define REQUIRE_GT DOCTEST_REQUIRE_GT #define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__)
#define WARN_LT DOCTEST_WARN_LT #define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__)
#define CHECK_LT DOCTEST_CHECK_LT #define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__)
#define REQUIRE_LT DOCTEST_REQUIRE_LT #define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__)
#define WARN_GE DOCTEST_WARN_GE #define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__)
#define CHECK_GE DOCTEST_CHECK_GE #define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__)
#define REQUIRE_GE DOCTEST_REQUIRE_GE #define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__)
#define WARN_LE DOCTEST_WARN_LE #define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__)
#define CHECK_LE DOCTEST_CHECK_LE #define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__)
#define REQUIRE_LE DOCTEST_REQUIRE_LE #define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__)
#define WARN_UNARY DOCTEST_WARN_UNARY #define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__)
#define CHECK_UNARY DOCTEST_CHECK_UNARY #define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__)
#define REQUIRE_UNARY DOCTEST_REQUIRE_UNARY #define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__)
#define WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE #define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__)
#define CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE #define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__)
#define REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE #define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
// KEPT FOR BACKWARDS COMPATIBILITY // KEPT FOR BACKWARDS COMPATIBILITY
#define FAST_WARN_EQ DOCTEST_FAST_WARN_EQ #define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__)
#define FAST_CHECK_EQ DOCTEST_FAST_CHECK_EQ #define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__)
#define FAST_REQUIRE_EQ DOCTEST_FAST_REQUIRE_EQ #define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__)
#define FAST_WARN_NE DOCTEST_FAST_WARN_NE #define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__)
#define FAST_CHECK_NE DOCTEST_FAST_CHECK_NE #define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__)
#define FAST_REQUIRE_NE DOCTEST_FAST_REQUIRE_NE #define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__)
#define FAST_WARN_GT DOCTEST_FAST_WARN_GT #define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__)
#define FAST_CHECK_GT DOCTEST_FAST_CHECK_GT #define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__)
#define FAST_REQUIRE_GT DOCTEST_FAST_REQUIRE_GT #define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__)
#define FAST_WARN_LT DOCTEST_FAST_WARN_LT #define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__)
#define FAST_CHECK_LT DOCTEST_FAST_CHECK_LT #define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__)
#define FAST_REQUIRE_LT DOCTEST_FAST_REQUIRE_LT #define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__)
#define FAST_WARN_GE DOCTEST_FAST_WARN_GE #define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__)
#define FAST_CHECK_GE DOCTEST_FAST_CHECK_GE #define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__)
#define FAST_REQUIRE_GE DOCTEST_FAST_REQUIRE_GE #define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__)
#define FAST_WARN_LE DOCTEST_FAST_WARN_LE #define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__)
#define FAST_CHECK_LE DOCTEST_FAST_CHECK_LE #define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__)
#define FAST_REQUIRE_LE DOCTEST_FAST_REQUIRE_LE #define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__)
#define FAST_WARN_UNARY DOCTEST_FAST_WARN_UNARY #define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__)
#define FAST_CHECK_UNARY DOCTEST_FAST_CHECK_UNARY #define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__)
#define FAST_REQUIRE_UNARY DOCTEST_FAST_REQUIRE_UNARY #define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__)
#define FAST_WARN_UNARY_FALSE DOCTEST_FAST_WARN_UNARY_FALSE #define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__)
#define FAST_CHECK_UNARY_FALSE DOCTEST_FAST_CHECK_UNARY_FALSE #define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__)
#define FAST_REQUIRE_UNARY_FALSE DOCTEST_FAST_REQUIRE_UNARY_FALSE #define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
#define TEST_CASE_TEMPLATE_INSTANTIATE DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE #define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__)
#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES #endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
...@@ -2689,6 +2746,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers") ...@@ -2689,6 +2746,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function") DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path")
DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING_PUSH
DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas")
...@@ -2794,11 +2852,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN ...@@ -2794,11 +2852,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#ifdef __AFXDLL #ifdef __AFXDLL
#include <AfxWin.h> #include <AfxWin.h>
#else #else
#if defined(__MINGW32__) || defined(__MINGW64__)
#include <windows.h> #include <windows.h>
#else // MINGW
#include <Windows.h>
#endif // MINGW
#endif #endif
#include <io.h> #include <io.h>
...@@ -2834,12 +2888,24 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END ...@@ -2834,12 +2888,24 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
#define DOCTEST_THREAD_LOCAL thread_local #define DOCTEST_THREAD_LOCAL thread_local
#endif #endif
#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES
#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32
#endif
#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE
#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64
#endif
#ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS #ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
#define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX #define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX
#else #else
#define DOCTEST_OPTIONS_PREFIX_DISPLAY "" #define DOCTEST_OPTIONS_PREFIX_DISPLAY ""
#endif #endif
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
#endif
namespace doctest { namespace doctest {
bool is_running_in_test = false; bool is_running_in_test = false;
...@@ -2972,18 +3038,105 @@ typedef timer_large_integer::type ticks_t; ...@@ -2972,18 +3038,105 @@ typedef timer_large_integer::type ticks_t;
ticks_t m_ticks = 0; ticks_t m_ticks = 0;
}; };
#ifdef DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
template <typename T>
using AtomicOrMultiLaneAtomic = std::atomic<T>;
#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
// Provides a multilane implementation of an atomic variable that supports add, sub, load,
// store. Instead of using a single atomic variable, this splits up into multiple ones,
// each sitting on a separate cache line. The goal is to provide a speedup when most
// operations are modifying. It achieves this with two properties:
//
// * Multiple atomics are used, so chance of congestion from the same atomic is reduced.
// * Each atomic sits on a separate cache line, so false sharing is reduced.
//
// The disadvantage is that there is a small overhead due to the use of TLS, and load/store
// is slower because all atomics have to be accessed.
template <typename T>
class MultiLaneAtomic
{
struct CacheLineAlignedAtomic
{
std::atomic<T> atomic{};
char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(std::atomic<T>)];
};
CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES];
static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE,
"guarantee one atomic takes exactly one cache line");
public:
T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; }
T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); }
T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
return myAtomic().fetch_add(arg, order);
}
T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
return myAtomic().fetch_sub(arg, order);
}
operator T() const DOCTEST_NOEXCEPT { return load(); }
T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT {
auto result = T();
for(auto const& c : m_atomics) {
result += c.atomic.load(order);
}
return result;
}
T operator=(T desired) DOCTEST_NOEXCEPT {
store(desired);
return desired;
}
void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
// first value becomes desired", all others become 0.
for(auto& c : m_atomics) {
c.atomic.store(desired, order);
desired = {};
}
}
private:
// Each thread has a different atomic that it operates on. If more than NumLanes threads
// use this, some will use the same atomic. So performance will degrate a bit, but still
// everything will work.
//
// The logic here is a bit tricky. The call should be as fast as possible, so that there
// is minimal to no overhead in determining the correct atomic for the current thread.
//
// 1. A global static counter laneCounter counts continuously up.
// 2. Each successive thread will use modulo operation of that counter so it gets an atomic
// assigned in a round-robin fashion.
// 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with
// little overhead.
std::atomic<T>& myAtomic() DOCTEST_NOEXCEPT {
static std::atomic<size_t> laneCounter;
DOCTEST_THREAD_LOCAL size_t tlsLaneIdx =
laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES;
return m_atomics[tlsLaneIdx].atomic;
}
};
template <typename T>
using AtomicOrMultiLaneAtomic = MultiLaneAtomic<T>;
#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
// this holds both parameters from the command line and runtime data for tests // this holds both parameters from the command line and runtime data for tests
struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats
{ {
std::atomic<int> numAssertsCurrentTest_atomic; AtomicOrMultiLaneAtomic<int> numAssertsCurrentTest_atomic;
std::atomic<int> numAssertsFailedCurrentTest_atomic; AtomicOrMultiLaneAtomic<int> numAssertsFailedCurrentTest_atomic;
std::vector<std::vector<String>> filters = decltype(filters)(9); // 9 different filters std::vector<std::vector<String>> filters = decltype(filters)(9); // 9 different filters
std::vector<IReporter*> reporters_currently_used; std::vector<IReporter*> reporters_currently_used;
const TestCase* currentTest = nullptr;
assert_handler ah = nullptr; assert_handler ah = nullptr;
Timer timer; Timer timer;
...@@ -3093,14 +3246,16 @@ String::String(const char* in) ...@@ -3093,14 +3246,16 @@ String::String(const char* in)
String::String(const char* in, unsigned in_size) { String::String(const char* in, unsigned in_size) {
using namespace std; using namespace std;
if(in_size <= last) { if(in_size <= last) {
memcpy(buf, in, in_size + 1); memcpy(buf, in, in_size);
buf[in_size] = '\0';
setLast(last - in_size); setLast(last - in_size);
} else { } else {
setOnHeap(); setOnHeap();
data.size = in_size; data.size = in_size;
data.capacity = data.size + 1; data.capacity = data.size + 1;
data.ptr = new char[data.capacity]; data.ptr = new char[data.capacity];
memcpy(data.ptr, in, in_size + 1); memcpy(data.ptr, in, in_size);
data.ptr[in_size] = '\0';
} }
} }
...@@ -3471,7 +3626,7 @@ int registerReporter(const char*, int, IReporter*) { return 0; } ...@@ -3471,7 +3626,7 @@ int registerReporter(const char*, int, IReporter*) { return 0; }
namespace doctest_detail_test_suite_ns { namespace doctest_detail_test_suite_ns {
// holds the current test suite // holds the current test suite
doctest::detail::TestSuite& getCurrentTestSuite() { doctest::detail::TestSuite& getCurrentTestSuite() {
static doctest::detail::TestSuite data; static doctest::detail::TestSuite data{};
return data; return data;
} }
} // namespace doctest_detail_test_suite_ns } // namespace doctest_detail_test_suite_ns
...@@ -3583,7 +3738,7 @@ namespace detail { ...@@ -3583,7 +3738,7 @@ namespace detail {
Subcase::Subcase(const String& name, const char* file, int line) Subcase::Subcase(const String& name, const char* file, int line)
: m_signature({name, file, line}) { : m_signature({name, file, line}) {
ContextState* s = g_cs; auto* s = g_cs;
// check subcase filters // check subcase filters
if(s->subcasesStack.size() < size_t(s->subcase_filter_levels)) { if(s->subcasesStack.size() < size_t(s->subcase_filter_levels)) {
...@@ -3625,7 +3780,7 @@ namespace detail { ...@@ -3625,7 +3780,7 @@ namespace detail {
g_cs->subcasesPassed.insert(g_cs->subcasesStack); g_cs->subcasesPassed.insert(g_cs->subcasesStack);
g_cs->subcasesStack.pop_back(); g_cs->subcasesStack.pop_back();
#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L #if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
if(std::uncaught_exceptions() > 0 if(std::uncaught_exceptions() > 0
#else #else
if(std::uncaught_exception() if(std::uncaught_exception()
...@@ -3660,6 +3815,8 @@ namespace detail { ...@@ -3660,6 +3815,8 @@ namespace detail {
// clear state // clear state
m_description = nullptr; m_description = nullptr;
m_skip = false; m_skip = false;
m_no_breaks = false;
m_no_output = false;
m_may_fail = false; m_may_fail = false;
m_should_fail = false; m_should_fail = false;
m_expected_failures = 0; m_expected_failures = 0;
...@@ -3675,6 +3832,8 @@ namespace detail { ...@@ -3675,6 +3832,8 @@ namespace detail {
m_test_suite = test_suite.m_test_suite; m_test_suite = test_suite.m_test_suite;
m_description = test_suite.m_description; m_description = test_suite.m_description;
m_skip = test_suite.m_skip; m_skip = test_suite.m_skip;
m_no_breaks = test_suite.m_no_breaks;
m_no_output = test_suite.m_no_output;
m_may_fail = test_suite.m_may_fail; m_may_fail = test_suite.m_may_fail;
m_should_fail = test_suite.m_should_fail; m_should_fail = test_suite.m_should_fail;
m_expected_failures = test_suite.m_expected_failures; m_expected_failures = test_suite.m_expected_failures;
...@@ -3721,14 +3880,20 @@ namespace detail { ...@@ -3721,14 +3880,20 @@ namespace detail {
// this will be used only to differentiate between test cases - not relevant for sorting // this will be used only to differentiate between test cases - not relevant for sorting
if(m_line != other.m_line) if(m_line != other.m_line)
return m_line < other.m_line; return m_line < other.m_line;
const int file_cmp = m_file.compare(other.m_file);
if(file_cmp != 0)
return file_cmp < 0;
const int name_cmp = strcmp(m_name, other.m_name); const int name_cmp = strcmp(m_name, other.m_name);
if(name_cmp != 0) if(name_cmp != 0)
return name_cmp < 0; return name_cmp < 0;
const int file_cmp = m_file.compare(other.m_file);
if(file_cmp != 0)
return file_cmp < 0;
return m_template_id < other.m_template_id; return m_template_id < other.m_template_id;
} }
// all the registered tests
std::set<TestCase>& getRegisteredTests() {
static std::set<TestCase> data;
return data;
}
} // namespace detail } // namespace detail
namespace { namespace {
using namespace detail; using namespace detail;
...@@ -3760,12 +3925,6 @@ namespace { ...@@ -3760,12 +3925,6 @@ namespace {
return suiteOrderComparator(lhs, rhs); return suiteOrderComparator(lhs, rhs);
} }
// all the registered tests
std::set<TestCase>& getRegisteredTests() {
static std::set<TestCase> data;
return data;
}
#ifdef DOCTEST_CONFIG_COLORS_WINDOWS #ifdef DOCTEST_CONFIG_COLORS_WINDOWS
HANDLE g_stdoutHandle; HANDLE g_stdoutHandle;
WORD g_origFgAttrs; WORD g_origFgAttrs;
...@@ -3994,7 +4153,7 @@ namespace detail { ...@@ -3994,7 +4153,7 @@ namespace detail {
// ContextScope has been destroyed (base class destructors run after derived class destructors). // ContextScope has been destroyed (base class destructors run after derived class destructors).
// Instead, ContextScope calls this method directly from its destructor. // Instead, ContextScope calls this method directly from its destructor.
void ContextScopeBase::destroy() { void ContextScopeBase::destroy() {
#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L #if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
if(std::uncaught_exceptions() > 0) { if(std::uncaught_exceptions() > 0) {
#else #else
if(std::uncaught_exception()) { if(std::uncaught_exception()) {
...@@ -4016,7 +4175,9 @@ namespace { ...@@ -4016,7 +4175,9 @@ namespace {
#if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) #if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
struct FatalConditionHandler struct FatalConditionHandler
{ {
void reset() {} static void reset() {}
static void allocateAltStackMem() {}
static void freeAltStackMem() {}
}; };
#else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH #else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
...@@ -4069,6 +4230,9 @@ namespace { ...@@ -4069,6 +4230,9 @@ namespace {
std::exit(EXIT_FAILURE); std::exit(EXIT_FAILURE);
} }
static void allocateAltStackMem() {}
static void freeAltStackMem() {}
FatalConditionHandler() { FatalConditionHandler() {
isSet = true; isSet = true;
// 32k seems enough for doctest to handle stack overflow, // 32k seems enough for doctest to handle stack overflow,
...@@ -4086,7 +4250,7 @@ namespace { ...@@ -4086,7 +4250,7 @@ namespace {
// - std::terminate is called FROM THE TEST RUNNER THREAD // - std::terminate is called FROM THE TEST RUNNER THREAD
// - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD
original_terminate_handler = std::get_terminate(); original_terminate_handler = std::get_terminate();
std::set_terminate([]() noexcept { std::set_terminate([]() DOCTEST_NOEXCEPT {
reportFatal("Terminate handler called"); reportFatal("Terminate handler called");
if(isDebuggerActive() && !g_cs->no_breaks) if(isDebuggerActive() && !g_cs->no_breaks)
DOCTEST_BREAK_INTO_DEBUGGER(); DOCTEST_BREAK_INTO_DEBUGGER();
...@@ -4097,7 +4261,7 @@ namespace { ...@@ -4097,7 +4261,7 @@ namespace {
// - std::terminate is called FROM A DIFFERENT THREAD // - std::terminate is called FROM A DIFFERENT THREAD
// - an exception is thrown from a destructor FROM A DIFFERENT THREAD // - an exception is thrown from a destructor FROM A DIFFERENT THREAD
// - an uncaught exception is thrown FROM A DIFFERENT THREAD // - an uncaught exception is thrown FROM A DIFFERENT THREAD
prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) noexcept { prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT {
if(signal == SIGABRT) { if(signal == SIGABRT) {
reportFatal("SIGABRT - Abort (abnormal termination) signal"); reportFatal("SIGABRT - Abort (abnormal termination) signal");
if(isDebuggerActive() && !g_cs->no_breaks) if(isDebuggerActive() && !g_cs->no_breaks)
...@@ -4135,8 +4299,8 @@ namespace { ...@@ -4135,8 +4299,8 @@ namespace {
SetErrorMode(prev_error_mode_1); SetErrorMode(prev_error_mode_1);
_set_error_mode(prev_error_mode_2); _set_error_mode(prev_error_mode_2);
_set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
_CrtSetReportMode(_CRT_ASSERT, prev_report_mode); static_cast<void>(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode));
_CrtSetReportFile(_CRT_ASSERT, prev_report_file); static_cast<void>(_CrtSetReportFile(_CRT_ASSERT, prev_report_file));
isSet = false; isSet = false;
} }
} }
...@@ -4186,7 +4350,8 @@ namespace { ...@@ -4186,7 +4350,8 @@ namespace {
static bool isSet; static bool isSet;
static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)];
static stack_t oldSigStack; static stack_t oldSigStack;
static char altStackMem[4 * SIGSTKSZ]; static size_t altStackSize;
static char* altStackMem;
static void handleSignal(int sig) { static void handleSignal(int sig) {
const char* name = "<unknown signal>"; const char* name = "<unknown signal>";
...@@ -4202,11 +4367,19 @@ namespace { ...@@ -4202,11 +4367,19 @@ namespace {
raise(sig); raise(sig);
} }
static void allocateAltStackMem() {
altStackMem = new char[altStackSize];
}
static void freeAltStackMem() {
delete[] altStackMem;
}
FatalConditionHandler() { FatalConditionHandler() {
isSet = true; isSet = true;
stack_t sigStack; stack_t sigStack;
sigStack.ss_sp = altStackMem; sigStack.ss_sp = altStackMem;
sigStack.ss_size = sizeof(altStackMem); sigStack.ss_size = altStackSize;
sigStack.ss_flags = 0; sigStack.ss_flags = 0;
sigaltstack(&sigStack, &oldSigStack); sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = {}; struct sigaction sa = {};
...@@ -4234,7 +4407,8 @@ namespace { ...@@ -4234,7 +4407,8 @@ namespace {
bool FatalConditionHandler::isSet = false; bool FatalConditionHandler::isSet = false;
struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {};
stack_t FatalConditionHandler::oldSigStack = {}; stack_t FatalConditionHandler::oldSigStack = {};
char FatalConditionHandler::altStackMem[] = {}; size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ;
char* FatalConditionHandler::altStackMem = nullptr;
#endif // DOCTEST_PLATFORM_WINDOWS #endif // DOCTEST_PLATFORM_WINDOWS
#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
...@@ -4336,8 +4510,8 @@ namespace detail { ...@@ -4336,8 +4510,8 @@ namespace detail {
failed_out_of_a_testing_context(*this); failed_out_of_a_testing_context(*this);
} }
return m_failed && isDebuggerActive() && return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks &&
!getContextOptions()->no_breaks; // break into debugger (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
} }
void ResultBuilder::react() const { void ResultBuilder::react() const {
...@@ -4387,7 +4561,8 @@ namespace detail { ...@@ -4387,7 +4561,8 @@ namespace detail {
addFailedAssert(m_severity); addFailedAssert(m_severity);
} }
return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn; // break return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn &&
(g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
} }
void MessageBuilder::react() { void MessageBuilder::react() {
...@@ -5495,7 +5670,7 @@ namespace { ...@@ -5495,7 +5670,7 @@ namespace {
<< Whitespace(sizePrefixDisplay*1) << "output filename\n"; << Whitespace(sizePrefixDisplay*1) << "output filename\n";
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by=<string> " s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by=<string> "
<< Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n"; << Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n";
s << Whitespace(sizePrefixDisplay*3) << " <string> - by [file/suite/name/rand]\n"; s << Whitespace(sizePrefixDisplay*3) << " <string> - [file/suite/name/rand/none]\n";
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed=<int> " s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed=<int> "
<< Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n"; << Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n";
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first=<int> " s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first=<int> "
...@@ -5668,6 +5843,9 @@ namespace { ...@@ -5668,6 +5843,9 @@ namespace {
} }
void test_case_end(const CurrentTestCaseStats& st) override { void test_case_end(const CurrentTestCaseStats& st) override {
if(tc->m_no_output)
return;
// log the preamble of the test case only if there is something // log the preamble of the test case only if there is something
// else to print - something other than that an assert has failed // else to print - something other than that an assert has failed
if(opt.duration || if(opt.duration ||
...@@ -5702,6 +5880,9 @@ namespace { ...@@ -5702,6 +5880,9 @@ namespace {
} }
void test_case_exception(const TestCaseException& e) override { void test_case_exception(const TestCaseException& e) override {
if(tc->m_no_output)
return;
logTestStart(); logTestStart();
file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); file_line_to_stream(tc->m_file.c_str(), tc->m_line, " ");
...@@ -5736,7 +5917,7 @@ namespace { ...@@ -5736,7 +5917,7 @@ namespace {
} }
void log_assert(const AssertData& rb) override { void log_assert(const AssertData& rb) override {
if(!rb.m_failed && !opt.success) if((!rb.m_failed && !opt.success) || tc->m_no_output)
return; return;
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
...@@ -5752,6 +5933,9 @@ namespace { ...@@ -5752,6 +5933,9 @@ namespace {
} }
void log_message(const MessageData& mb) override { void log_message(const MessageData& mb) override {
if(tc->m_no_output)
return;
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
logTestStart(); logTestStart();
...@@ -5782,8 +5966,10 @@ namespace { ...@@ -5782,8 +5966,10 @@ namespace {
bool with_col = g_no_colors; \ bool with_col = g_no_colors; \
g_no_colors = false; \ g_no_colors = false; \
ConsoleReporter::func(arg); \ ConsoleReporter::func(arg); \
if(oss.tellp() != std::streampos{}) { \
DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \
oss.str(""); \ oss.str(""); \
} \
g_no_colors = with_col; \ g_no_colors = with_col; \
} }
...@@ -5970,7 +6156,7 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { ...@@ -5970,7 +6156,7 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ #define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \
if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \
parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \
p->var = !!intRes; \ p->var = static_cast<bool>(intRes); \
else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \
parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \
p->var = true; \ p->var = true; \
...@@ -6115,7 +6301,11 @@ int Context::run() { ...@@ -6115,7 +6301,11 @@ int Context::run() {
p->cout = &fstr; p->cout = &fstr;
} }
FatalConditionHandler::allocateAltStackMem();
auto cleanup_and_return = [&]() { auto cleanup_and_return = [&]() {
FatalConditionHandler::freeAltStackMem();
if(fstr.is_open()) if(fstr.is_open())
fstr.close(); fstr.close();
...@@ -6187,6 +6377,9 @@ int Context::run() { ...@@ -6187,6 +6377,9 @@ int Context::run() {
first[i] = first[idxToSwap]; first[i] = first[idxToSwap];
first[idxToSwap] = temp; first[idxToSwap] = temp;
} }
} else if(p->order_by.compare("none", true) == 0) {
// means no sorting - beneficial for death tests which call into the executable
// with a specific test case in mind - we don't want to slow down the startup times
} }
} }
...@@ -6286,10 +6479,13 @@ int Context::run() { ...@@ -6286,10 +6479,13 @@ int Context::run() {
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
try { try {
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS #endif // DOCTEST_CONFIG_NO_EXCEPTIONS
// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method)
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable
FatalConditionHandler fatalConditionHandler; // Handle signals FatalConditionHandler fatalConditionHandler; // Handle signals
// execute the test // execute the test
tc.m_test(); tc.m_test();
fatalConditionHandler.reset(); fatalConditionHandler.reset();
DOCTEST_MSVC_SUPPRESS_WARNING_POP
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
} catch(const TestFailureException&) { } catch(const TestFailureException&) {
p->failure_flags |= TestCaseFailureReason::AssertFailure; p->failure_flags |= TestCaseFailureReason::AssertFailure;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment