summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDidier Raboud <odyx@debian.org>2019-06-21 16:42:11 +0200
committerDidier Raboud <odyx@debian.org>2019-06-21 16:42:11 +0200
commit0dcd87acca6a8134f9ef0f2ccf9d14b792cd055e (patch)
tree634dc3c06af123d82ef0b16a9f9a82667a1b3137
parent873e4e3f3119c022f1295c9e701b3246b8971c15 (diff)
parentb23c9f8f404d86ab14c3a6e7c1a2229578bb6373 (diff)
record new upstream branch and merge it
-rw-r--r--.travis.yml19
-rw-r--r--CHANGELOG.md20
-rw-r--r--CMakeLists.txt5
-rw-r--r--README.md2
-rw-r--r--appveyor.yml1
-rw-r--r--debian/.git-dpm14
-rw-r--r--doc/markdown/build-systems.md2
-rw-r--r--doc/markdown/features.md1
-rw-r--r--doc/markdown/roadmap.md1
-rw-r--r--doctest/doctest.h190
-rw-r--r--doctest/parts/doctest.cpp105
-rw-r--r--doctest/parts/doctest_fwd.h85
-rw-r--r--examples/all_features/concurrency.cpp2
-rw-r--r--examples/all_features/test_output/version.txt2
-rw-r--r--examples/all_features/test_output/version_xml.txt2
-rw-r--r--meson.build3
-rw-r--r--scripts/cmake/Config.cmake.in7
-rw-r--r--scripts/cmake/doctest.cmake175
-rw-r--r--scripts/cmake/doctestAddTests.cmake81
-rw-r--r--scripts/coverage_maxout.cpp6
-rw-r--r--scripts/release_process.md2
-rw-r--r--scripts/version.txt2
22 files changed, 510 insertions, 217 deletions
diff --git a/.travis.yml b/.travis.yml
index 1522916..99be2f9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -251,11 +251,22 @@ matrix:
# static code analysis
- env: COMPILER=clang++-4.0 STATIC_CODE_ANALYSIS=true
-
- # GCC 9
- - env: COMPILER=g++-9 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold" TSAN_CXX_FLAGS="-ltsan"
+
+ # GCC 4.8
+ - env: COMPILER=g++-4.8 HAS_ASAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold" TSAN_CXX_FLAGS="-ltsan"
+ compiler: gcc
+ # GCC 4.9
+ - env: COMPILER=g++-4.9 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold" TSAN_CXX_FLAGS="-ltsan"
+ compiler: gcc
+ # GCC 5
+ - env: COMPILER=g++-5 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold" TSAN_CXX_FLAGS="-ltsan"
+ compiler: gcc
+ # GCC 6
+ - env: COMPILER=g++-6 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold" TSAN_CXX_FLAGS="-ltsan"
+ compiler: gcc
+ # GCC 7
+ - env: COMPILER=g++-7 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold" TSAN_CXX_FLAGS="-ltsan"
compiler: gcc
- sudo: required
install:
- if [[ "${CODE_COVERAGE}" == "true" ]]; then gem install coveralls-lcov ; fi
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 056d1c6..e41950c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,24 @@
# Change Log
+## [2.3.3](https://github.com/onqtam/doctest/tree/2.3.3) (2019-06-02)
+[Full Changelog](https://github.com/onqtam/doctest/compare/2.3.2...2.3.3)
+
+**Closed issues:**
+
+- Build fails with gcc9 because of -Wstrict-overflow=5 which is too high [\#241](https://github.com/onqtam/doctest/issues/241)
+- doctest given defined with short macro name [\#239](https://github.com/onqtam/doctest/issues/239)
+- Splitting templated test across different translation units [\#238](https://github.com/onqtam/doctest/issues/238)
+- Compile errors with iosfwd.h and Visual Studio 2019 Preview [\#183](https://github.com/onqtam/doctest/issues/183)
+- Add CMake test support as catch\_discover\_tests\(\) in Catch2 [\#171](https://github.com/onqtam/doctest/issues/171)
+- Doctest is not able to compile on OSX [\#126](https://github.com/onqtam/doctest/issues/126)
+
+**Merged pull requests:**
+
+- fix \#239 - use long macro name [\#240](https://github.com/onqtam/doctest/pull/240) ([m-bd](https://github.com/m-bd))
+- Add doctest\_discover\_tests\(\) [\#236](https://github.com/onqtam/doctest/pull/236) ([RedDwarf69](https://github.com/RedDwarf69))
+- Ignore redundant-decls warning on MinGW [\#235](https://github.com/onqtam/doctest/pull/235) ([AMS21](https://github.com/AMS21))
+- Fixed meson build file dependency declaration [\#233](https://github.com/onqtam/doctest/pull/233) ([jormundgand](https://github.com/jormundgand))
+
## [2.3.2](https://github.com/onqtam/doctest/tree/2.3.2) (2019-05-06)
[Full Changelog](https://github.com/onqtam/doctest/compare/2.3.1...2.3.2)
@@ -177,7 +196,6 @@
- Signal stack size too small on Linux [\#129](https://github.com/onqtam/doctest/issues/129)
- Support Intel Compiler [\#128](https://github.com/onqtam/doctest/issues/128)
- Please add support for MSVC 2005 [\#127](https://github.com/onqtam/doctest/issues/127)
-- Doctest is not able to compile on OSX [\#126](https://github.com/onqtam/doctest/issues/126)
- scan-build report "Dereference of null pointer" for function wildcmp [\#124](https://github.com/onqtam/doctest/issues/124)
- !!! BREAKING CHANGE \(console output only\) !!! - Emulate the error/warning format emitted by native compiler gcc/clang/msvc when printing test failures in the log [\#123](https://github.com/onqtam/doctest/issues/123)
- ARM builds: FTBFS on armhf - error: cast from 'const char\*' to 'const [\#118](https://github.com/onqtam/doctest/issues/118)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bd5ca4e..66b387b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -124,6 +124,11 @@ if(NOT ${DOCTEST_NO_INSTALL})
)
install(
+ FILES "scripts/cmake/doctest.cmake" "scripts/cmake/doctestAddTests.cmake"
+ DESTINATION "${config_install_dir}"
+ )
+
+ install(
EXPORT "${targets_export_name}"
NAMESPACE "${namespace}"
DESTINATION "${config_install_dir}"
diff --git a/README.md b/README.md
index 7d40e4e..fc0ec07 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/503/badge)](https://bestpractices.coreinfrastructure.org/projects/503)
[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/onqtam/doctest.svg)](https://lgtm.com/projects/g/onqtam/doctest/context:cpp)
[![Join the chat at https://gitter.im/onqtam/doctest](https://badges.gitter.im/onqtam/doctest.svg)](https://gitter.im/onqtam/doctest?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-[![Try it online](https://img.shields.io/badge/try%20it-online-orange.svg)](https://wandbox.org/permlink/K1BuLId1qC8wCJ52)
+[![Try it online](https://img.shields.io/badge/try%20it-online-orange.svg)](https://wandbox.org/permlink/cSNITptGIf1c0jrg)
<!--
[![Language](https://img.shields.io/badge/language-C++-blue.svg)](https://isocpp.org/)
[![documentation](https://img.shields.io/badge/documentation%20%20-online-blue.svg)](https://github.com/onqtam/doctest/blob/master/doc/markdown/readme.md#reference)
diff --git a/appveyor.yml b/appveyor.yml
index 26c170d..83538dd 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -36,6 +36,7 @@ install:
- IF "%gen%" == "MinGW Makefiles" 7z x x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z -oc:\mingw > nul
build_script:
+ - cmake --version
# workaround for CMake not wanting sh.exe on PATH for MinGW
- IF "%gen%" == "MinGW Makefiles" set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
- IF "%gen%" == "MinGW Makefiles" set PATH=C:\mingw\mingw64\bin;%PATH%
diff --git a/debian/.git-dpm b/debian/.git-dpm
index ef60119..ba60331 100644
--- a/debian/.git-dpm
+++ b/debian/.git-dpm
@@ -1,8 +1,8 @@
# see git-dpm(1) from git-dpm package
-0a344c4dd7ddc425b28b22e24a310f61b65d8dc1
-0a344c4dd7ddc425b28b22e24a310f61b65d8dc1
-0a344c4dd7ddc425b28b22e24a310f61b65d8dc1
-0a344c4dd7ddc425b28b22e24a310f61b65d8dc1
-doctest_2.3.2+repack0.orig.tar.xz
-c6172a8362db7ab72864fecbb52524b67c702530
-1984860
+b23c9f8f404d86ab14c3a6e7c1a2229578bb6373
+b23c9f8f404d86ab14c3a6e7c1a2229578bb6373
+b23c9f8f404d86ab14c3a6e7c1a2229578bb6373
+b23c9f8f404d86ab14c3a6e7c1a2229578bb6373
+doctest_2.3.3+repack0.orig.tar.xz
+9476a3017b7253124202dcba2e626c5a525bc2f9
+1988196
diff --git a/doc/markdown/build-systems.md b/doc/markdown/build-systems.md
index 740f6ca..dfebf52 100644
--- a/doc/markdown/build-systems.md
+++ b/doc/markdown/build-systems.md
@@ -63,6 +63,8 @@ target_link_libraries(my_tests doctest)
- The ```CMakeLists.txt``` file of the doctest repository has ```install()``` commands so you could also use doctest as a package.
+- To discover tests from an executable and register them in ctest you could use [```doctest_discover_tests(<target>)``` from scripts/cmake/doctest.cmake](../../scripts/cmake/doctest.cmake) - read the comments in the file on how to use it. It works just like [the same functionality in Catch](https://github.com/catchorg/Catch2/blob/master/docs/cmake-integration.md#automatic-test-registration).
+
### Package managers
**doctest** is available through the following package managers:
diff --git a/doc/markdown/features.md b/doc/markdown/features.md
index 6c1cb92..d571bb1 100644
--- a/doc/markdown/features.md
+++ b/doc/markdown/features.md
@@ -71,6 +71,7 @@
- controlling the order of test execution
- different ```doctest::Context```s can be created and ran many times within a single execution of the program
- ability to query if code is currently being ran in a test - ```doctest::is_running_in_test```
+- tests can be registered in CTest with the use of [```doctest_discover_tests(<target>)``` from scripts/cmake/doctest.cmake](../../scripts/cmake/doctest.cmake)
There is a list of planned features which are all important and big - see the [**roadmap**](roadmap.md).
diff --git a/doc/markdown/roadmap.md b/doc/markdown/roadmap.md
index 11c3574..bb54776 100644
--- a/doc/markdown/roadmap.md
+++ b/doc/markdown/roadmap.md
@@ -76,6 +76,7 @@ Planned features for future releases - order changes constantly...
### Things that are being considered but not part of the roadmap yet:
+- add ability to print a diff for strings/values instead of the whole 2 versions (gtest does that)
- add LIKELY & friends for the conditions of asserts - look at BOOST_LIKELY, ppk_assert, foonathan/debug_assert, etc
- ability for users to register their own command line options and access them later on
- fix this: https://github.com/catchorg/Catch2/issues/1292
diff --git a/doctest/doctest.h b/doctest/doctest.h
index 69a0fe0..68bc7f1 100644
--- a/doctest/doctest.h
+++ b/doctest/doctest.h
@@ -48,8 +48,8 @@
#define DOCTEST_VERSION_MAJOR 2
#define DOCTEST_VERSION_MINOR 3
-#define DOCTEST_VERSION_PATCH 2
-#define DOCTEST_VERSION_STR "2.3.2"
+#define DOCTEST_VERSION_PATCH 3
+#define DOCTEST_VERSION_STR "2.3.3"
#define DOCTEST_VERSION \
(DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
@@ -227,7 +227,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr
// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
// MSVC version table:
// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
-// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) << NOT YET RELEASED - April 2 2019
+// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
@@ -362,7 +362,9 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr
#elif DOCTEST_MSVC
#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
#elif defined(__MINGW32__)
+DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls")
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+DOCTEST_GCC_SUPPRESS_WARNING_POP
#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
#else // linux
#define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0)
@@ -376,6 +378,10 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak();
#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
#include <iosfwd>
#include <cstddef>
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+#include <ostream>
+#endif // VS 2019
#else // DOCTEST_CONFIG_USE_STD_HEADERS
#if DOCTEST_CLANG
@@ -405,6 +411,14 @@ class basic_ostream;
typedef basic_ostream<char, char_traits<char>> ostream;
template <class... Types>
class tuple;
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+template <class _Ty>
+class allocator;
+template <class _Elem, class _Traits, class _Alloc>
+class basic_string;
+using string = basic_string<char, char_traits<char>, allocator<char>>;
+#endif // VS 2019
DOCTEST_STD_NAMESPACE_END
DOCTEST_MSVC_SUPPRESS_WARNING_POP
@@ -885,6 +899,11 @@ DOCTEST_INTERFACE String toString(int long long in);
DOCTEST_INTERFACE String toString(int long long unsigned in);
DOCTEST_INTERFACE String toString(std::nullptr_t in);
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+DOCTEST_INTERFACE String toString(const std::string& in);
+#endif // VS 2019
+
class DOCTEST_INTERFACE Approx
{
public:
@@ -996,7 +1015,7 @@ namespace detail {
};
DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at);
-
+
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
[[noreturn]]
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
@@ -1286,6 +1305,9 @@ namespace detail {
DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts);
DOCTEST_INTERFACE bool isDebuggerActive();
+ template<typename T>
+ int instantiationHelper(const T&) { return 0; }
+
namespace binaryAssertComparison {
enum Enum
{
@@ -1300,7 +1322,7 @@ namespace detail {
// clang-format off
template <int, class L, class R> struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } };
-
+
#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \
template <class L, class R> struct RelationalComparator<n, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } };
// clang-format on
@@ -1921,14 +1943,6 @@ int registerReporter(const char* name, int priority) {
} \
typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-// for typed tests
-#define DOCTEST_REGISTER_TYPED_TEST_CASE_IMPL(func, type, decorators, idx) \
- doctest::detail::regTest( \
- doctest::detail::TestCase(func, __FILE__, __LINE__, \
- doctest_detail_test_suite_ns::getCurrentTestSuite(), \
- doctest::detail::type_to_string<type>(), idx) * \
- decorators)
-
#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \
template <typename T> \
static void func(); \
@@ -1938,15 +1952,19 @@ int registerReporter(const char* name, int priority) {
template <typename Type, typename... Rest> \
struct iter<std::tuple<Type, Rest...>> \
{ \
- iter(int line, int index) { \
- DOCTEST_REGISTER_TYPED_TEST_CASE_IMPL(func<Type>, Type, dec, line * 1000 + index); \
- iter<std::tuple<Rest...>>(line, index + 1); \
+ iter(const char* file, unsigned line, int index) { \
+ doctest::detail::regTest(doctest::detail::TestCase(func<Type>, file, line, \
+ doctest_detail_test_suite_ns::getCurrentTestSuite(), \
+ doctest::detail::type_to_string<Type>(), \
+ int(line) * 1000 + index) \
+ * dec); \
+ iter<std::tuple<Rest...>>(file, line, index + 1); \
} \
}; \
template <> \
struct iter<std::tuple<>> \
{ \
- iter(int, int) {} \
+ iter(const char*, unsigned, int) {} \
}; \
} \
template <typename T> \
@@ -1956,33 +1974,22 @@ int registerReporter(const char* name, int priority) {
DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \
DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_))
-#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(id, anon, ...) \
- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = [] { \
- DOCTEST_CAT(id, ITERATOR)<std::tuple<__VA_ARGS__>> DOCTEST_UNUSED DOCTEST_CAT( \
- anon, inner_dummy)(__LINE__, 0); \
- return 0; \
- }(); \
+#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = \
+ doctest::detail::instantiationHelper(DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0));\
DOCTEST_GLOBAL_NO_WARNINGS_END()
#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
- DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-#define DOCTEST_TEST_CASE_TEMPLATE_APPLY_IMPL(id, anon, ...) \
- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = [] { \
- DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__> DOCTEST_UNUSED DOCTEST_CAT(anon, inner_dummy)( \
- __LINE__, 0); \
- return 0; \
- }(); \
- DOCTEST_GLOBAL_NO_WARNINGS_END()
-
#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
- DOCTEST_TEST_CASE_TEMPLATE_APPLY_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \
typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \
DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \
- DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(anon, anon, __VA_ARGS__) \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \
template <typename T> \
static void anon()
@@ -2511,11 +2518,11 @@ constexpr T to_lvalue = x;
#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__)
#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id)
-#define DOCTEST_GIVEN(name) SUBCASE(" Given: " name)
-#define DOCTEST_WHEN(name) SUBCASE(" When: " name)
-#define DOCTEST_AND_WHEN(name) SUBCASE("And when: " name)
-#define DOCTEST_THEN(name) SUBCASE(" Then: " name)
-#define DOCTEST_AND_THEN(name) SUBCASE(" And: " name)
+#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name)
+#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name)
+#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name)
+#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name)
+#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name)
// clang-format on
// == SHORT VERSIONS OF THE MACROS
@@ -3394,6 +3401,11 @@ DOCTEST_TO_STRING_OVERLOAD(int long long unsigned, "%llu")
String toString(std::nullptr_t) { return "NULL"; }
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+String toString(const std::string& in) { return in.c_str(); }
+#endif // VS 2019
+
Approx::Approx(double value)
: m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
, m_scale(1.0)
@@ -3662,7 +3674,7 @@ namespace detail {
const char* type, int template_id) {
m_file = file;
m_line = line;
- m_name = nullptr;
+ m_name = nullptr; // will be later overridden in operator*
m_test_suite = test_suite.m_test_suite;
m_description = test_suite.m_description;
m_skip = test_suite.m_skip;
@@ -5329,9 +5341,9 @@ namespace {
if(num_stringified_contexts) {
auto stringified_contexts = get_stringified_contexts();
s << Color::None << " logged: ";
- for(int i = num_stringified_contexts - 1; i >= 0; --i) {
- s << (i == num_stringified_contexts - 1 ? "" : " ")
- << stringified_contexts[i] << "\n";
+ for(int i = num_stringified_contexts; i > 0; --i) {
+ s << (i == num_stringified_contexts ? "" : " ")
+ << stringified_contexts[i - 1] << "\n";
}
}
s << "\n" << Color::None;
@@ -5448,55 +5460,33 @@ namespace {
DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss;
#endif // DOCTEST_PLATFORM_WINDOWS
- // the implementation of parseFlag()
- bool parseFlagImpl(int argc, const char* const* argv, const char* pattern) {
- for(int i = argc - 1; i >= 0; --i) {
- auto temp = std::strstr(argv[i], pattern);
- if(temp && strlen(temp) == strlen(pattern)) {
- // eliminate strings in which the chars before the option are not '-'
- bool noBadCharsFound = true; //!OCLINT prefer early exits and continue
- while(temp != argv[i]) {
- if(*--temp != '-') {
- noBadCharsFound = false;
- break;
- }
- }
- if(noBadCharsFound && argv[i][0] == '-')
- return true;
- }
- }
- return false;
- }
-
- // locates a flag on the command line
- bool parseFlag(int argc, const char* const* argv, const char* pattern) {
-#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
- // offset (normally 3 for "dt-") to skip prefix
- if(parseFlagImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX)))
- return true;
-#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
- return parseFlagImpl(argc, argv, pattern);
- }
-
// the implementation of parseOption()
- bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String& res) {
- for(int i = argc - 1; i >= 0; --i) {
- auto temp = std::strstr(argv[i], pattern);
- if(temp) { //!OCLINT prefer early exits and continue
+ bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) {
+ // going from the end to the begining and stopping on the first occurance from the end
+ for(int i = argc; i > 0; --i) {
+ auto index = i - 1;
+ auto temp = std::strstr(argv[index], pattern);
+ if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue
// eliminate matches in which the chars before the option are not '-'
bool noBadCharsFound = true;
- auto curr = argv[i];
+ auto curr = argv[index];
while(curr != temp) {
if(*curr++ != '-') {
noBadCharsFound = false;
break;
}
}
- if(noBadCharsFound && argv[i][0] == '-') {
- temp += strlen(pattern);
- const unsigned len = strlen(temp);
- if(len) {
- res = temp;
+ if(noBadCharsFound && argv[index][0] == '-') {
+ if(value) {
+ // parsing the value of an option
+ temp += strlen(pattern);
+ const unsigned len = strlen(temp);
+ if(len) {
+ *value = temp;
+ return true;
+ }
+ } else {
+ // just a flag - no value
return true;
}
}
@@ -5506,22 +5496,28 @@ namespace {
}
// parses an option and returns the string after the '=' character
- bool parseOption(int argc, const char* const* argv, const char* pattern, String& res,
+ bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr,
const String& defaultVal = String()) {
- res = defaultVal;
+ if(value)
+ *value = defaultVal;
#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
// offset (normally 3 for "dt-") to skip prefix
- if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), res))
+ if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value))
return true;
#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
- return parseOptionImpl(argc, argv, pattern, res);
+ return parseOptionImpl(argc, argv, pattern, value);
+ }
+
+ // locates a flag on the command line
+ bool parseFlag(int argc, const char* const* argv, const char* pattern) {
+ return parseOption(argc, argv, pattern);
}
// parses a comma separated list of words after a pattern in one of the arguments in argv
bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern,
std::vector<String>& res) {
String filtersString;
- if(parseOption(argc, argv, pattern, filtersString)) {
+ if(parseOption(argc, argv, pattern, &filtersString)) {
// tokenize with "," as a separator
// cppcheck-suppress strtokCalled
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
@@ -5549,7 +5545,7 @@ namespace {
bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type,
int& res) {
String parsedValue;
- if(!parseOption(argc, argv, pattern, parsedValue))
+ if(!parseOption(argc, argv, pattern, &parsedValue))
return false;
if(type == 0) {
@@ -5646,8 +5642,8 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
p->var = default
#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \
- if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", strRes, default) || \
- parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", strRes, default) || \
+ if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \
+ parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \
withDefaults) \
p->var = strRes
@@ -5978,6 +5974,13 @@ int Context::run() {
DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata);
}
+ // see these issues on the reasoning for this:
+ // - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903
+ // - https://github.com/onqtam/doctest/issues/126
+ auto DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS = []() DOCTEST_NOINLINE
+ { std::cout << std::string(); };
+ DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS();
+
return cleanup_and_return();
}
@@ -6003,11 +6006,6 @@ namespace detail {
}
} // namespace detail
-// see these issues on the reasoning for this:
-// - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903
-// - https://github.com/onqtam/doctest/issues/126
-void DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS() { std::cout << std::string(); }
-
} // namespace doctest
#endif // DOCTEST_CONFIG_DISABLE
diff --git a/doctest/parts/doctest.cpp b/doctest/parts/doctest.cpp
index d4544af..64f0aa7 100644
--- a/doctest/parts/doctest.cpp
+++ b/doctest/parts/doctest.cpp
@@ -704,6 +704,11 @@ DOCTEST_TO_STRING_OVERLOAD(int long long unsigned, "%llu")
String toString(std::nullptr_t) { return "NULL"; }
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+String toString(const std::string& in) { return in.c_str(); }
+#endif // VS 2019
+
Approx::Approx(double value)
: m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
, m_scale(1.0)
@@ -972,7 +977,7 @@ namespace detail {
const char* type, int template_id) {
m_file = file;
m_line = line;
- m_name = nullptr;
+ m_name = nullptr; // will be later overridden in operator*
m_test_suite = test_suite.m_test_suite;
m_description = test_suite.m_description;
m_skip = test_suite.m_skip;
@@ -2639,9 +2644,9 @@ namespace {
if(num_stringified_contexts) {
auto stringified_contexts = get_stringified_contexts();
s << Color::None << " logged: ";
- for(int i = num_stringified_contexts - 1; i >= 0; --i) {
- s << (i == num_stringified_contexts - 1 ? "" : " ")
- << stringified_contexts[i] << "\n";
+ for(int i = num_stringified_contexts; i > 0; --i) {
+ s << (i == num_stringified_contexts ? "" : " ")
+ << stringified_contexts[i - 1] << "\n";
}
}
s << "\n" << Color::None;
@@ -2758,55 +2763,33 @@ namespace {
DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss;
#endif // DOCTEST_PLATFORM_WINDOWS
- // the implementation of parseFlag()
- bool parseFlagImpl(int argc, const char* const* argv, const char* pattern) {
- for(int i = argc - 1; i >= 0; --i) {
- auto temp = std::strstr(argv[i], pattern);
- if(temp && strlen(temp) == strlen(pattern)) {
- // eliminate strings in which the chars before the option are not '-'
- bool noBadCharsFound = true; //!OCLINT prefer early exits and continue
- while(temp != argv[i]) {
- if(*--temp != '-') {
- noBadCharsFound = false;
- break;
- }
- }
- if(noBadCharsFound && argv[i][0] == '-')
- return true;
- }
- }
- return false;
- }
-
- // locates a flag on the command line
- bool parseFlag(int argc, const char* const* argv, const char* pattern) {
-#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
- // offset (normally 3 for "dt-") to skip prefix
- if(parseFlagImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX)))
- return true;
-#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
- return parseFlagImpl(argc, argv, pattern);
- }
-
// the implementation of parseOption()
- bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String& res) {
- for(int i = argc - 1; i >= 0; --i) {
- auto temp = std::strstr(argv[i], pattern);
- if(temp) { //!OCLINT prefer early exits and continue
+ bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) {
+ // going from the end to the begining and stopping on the first occurance from the end
+ for(int i = argc; i > 0; --i) {
+ auto index = i - 1;
+ auto temp = std::strstr(argv[index], pattern);
+ if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue
// eliminate matches in which the chars before the option are not '-'
bool noBadCharsFound = true;
- auto curr = argv[i];
+ auto curr = argv[index];
while(curr != temp) {
if(*curr++ != '-') {
noBadCharsFound = false;
break;
}
}
- if(noBadCharsFound && argv[i][0] == '-') {
- temp += strlen(pattern);
- const unsigned len = strlen(temp);
- if(len) {
- res = temp;
+ if(noBadCharsFound && argv[index][0] == '-') {
+ if(value) {
+ // parsing the value of an option
+ temp += strlen(pattern);
+ const unsigned len = strlen(temp);
+ if(len) {
+ *value = temp;
+ return true;
+ }
+ } else {
+ // just a flag - no value
return true;
}
}
@@ -2816,22 +2799,28 @@ namespace {
}
// parses an option and returns the string after the '=' character
- bool parseOption(int argc, const char* const* argv, const char* pattern, String& res,
+ bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr,
const String& defaultVal = String()) {
- res = defaultVal;
+ if(value)
+ *value = defaultVal;
#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
// offset (normally 3 for "dt-") to skip prefix
- if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), res))
+ if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value))
return true;
#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
- return parseOptionImpl(argc, argv, pattern, res);
+ return parseOptionImpl(argc, argv, pattern, value);
+ }
+
+ // locates a flag on the command line
+ bool parseFlag(int argc, const char* const* argv, const char* pattern) {
+ return parseOption(argc, argv, pattern);
}
// parses a comma separated list of words after a pattern in one of the arguments in argv
bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern,
std::vector<String>& res) {
String filtersString;
- if(parseOption(argc, argv, pattern, filtersString)) {
+ if(parseOption(argc, argv, pattern, &filtersString)) {
// tokenize with "," as a separator
// cppcheck-suppress strtokCalled
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
@@ -2859,7 +2848,7 @@ namespace {
bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type,
int& res) {
String parsedValue;
- if(!parseOption(argc, argv, pattern, parsedValue))
+ if(!parseOption(argc, argv, pattern, &parsedValue))
return false;
if(type == 0) {
@@ -2956,8 +2945,8 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
p->var = default
#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \
- if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", strRes, default) || \
- parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", strRes, default) || \
+ if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \
+ parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \
withDefaults) \
p->var = strRes
@@ -3288,6 +3277,13 @@ int Context::run() {
DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata);
}
+ // see these issues on the reasoning for this:
+ // - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903
+ // - https://github.com/onqtam/doctest/issues/126
+ auto DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS = []() DOCTEST_NOINLINE
+ { std::cout << std::string(); };
+ DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS();
+
return cleanup_and_return();
}
@@ -3313,11 +3309,6 @@ namespace detail {
}
} // namespace detail
-// see these issues on the reasoning for this:
-// - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903
-// - https://github.com/onqtam/doctest/issues/126
-void DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS() { std::cout << std::string(); }
-
} // namespace doctest
#endif // DOCTEST_CONFIG_DISABLE
diff --git a/doctest/parts/doctest_fwd.h b/doctest/parts/doctest_fwd.h
index 43ca289..0142b24 100644
--- a/doctest/parts/doctest_fwd.h
+++ b/doctest/parts/doctest_fwd.h
@@ -45,8 +45,8 @@
#define DOCTEST_VERSION_MAJOR 2
#define DOCTEST_VERSION_MINOR 3
-#define DOCTEST_VERSION_PATCH 2
-#define DOCTEST_VERSION_STR "2.3.2"
+#define DOCTEST_VERSION_PATCH 3
+#define DOCTEST_VERSION_STR "2.3.3"
#define DOCTEST_VERSION \
(DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
@@ -224,7 +224,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr
// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
// MSVC version table:
// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
-// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) << NOT YET RELEASED - April 2 2019
+// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
@@ -359,7 +359,9 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr
#elif DOCTEST_MSVC
#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
#elif defined(__MINGW32__)
+DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls")
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+DOCTEST_GCC_SUPPRESS_WARNING_POP
#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
#else // linux
#define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0)
@@ -373,6 +375,10 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak();
#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
#include <iosfwd>
#include <cstddef>
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+#include <ostream>
+#endif // VS 2019
#else // DOCTEST_CONFIG_USE_STD_HEADERS
#if DOCTEST_CLANG
@@ -402,6 +408,14 @@ class basic_ostream;
typedef basic_ostream<char, char_traits<char>> ostream;
template <class... Types>
class tuple;
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+template <class _Ty>
+class allocator;
+template <class _Elem, class _Traits, class _Alloc>
+class basic_string;
+using string = basic_string<char, char_traits<char>, allocator<char>>;
+#endif // VS 2019
DOCTEST_STD_NAMESPACE_END
DOCTEST_MSVC_SUPPRESS_WARNING_POP
@@ -882,6 +896,11 @@ DOCTEST_INTERFACE String toString(int long long in);
DOCTEST_INTERFACE String toString(int long long unsigned in);
DOCTEST_INTERFACE String toString(std::nullptr_t in);
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+DOCTEST_INTERFACE String toString(const std::string& in);
+#endif // VS 2019
+
class DOCTEST_INTERFACE Approx
{
public:
@@ -993,7 +1012,7 @@ namespace detail {
};
DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at);
-
+
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
[[noreturn]]
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
@@ -1283,6 +1302,9 @@ namespace detail {
DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts);
DOCTEST_INTERFACE bool isDebuggerActive();
+ template<typename T>
+ int instantiationHelper(const T&) { return 0; }
+
namespace binaryAssertComparison {
enum Enum
{
@@ -1297,7 +1319,7 @@ namespace detail {
// clang-format off
template <int, class L, class R> struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } };
-
+
#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \
template <class L, class R> struct RelationalComparator<n, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } };
// clang-format on
@@ -1918,14 +1940,6 @@ int registerReporter(const char* name, int priority) {
} \
typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-// for typed tests
-#define DOCTEST_REGISTER_TYPED_TEST_CASE_IMPL(func, type, decorators, idx) \
- doctest::detail::regTest( \
- doctest::detail::TestCase(func, __FILE__, __LINE__, \
- doctest_detail_test_suite_ns::getCurrentTestSuite(), \
- doctest::detail::type_to_string<type>(), idx) * \
- decorators)
-
#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \
template <typename T> \
static void func(); \
@@ -1935,15 +1949,19 @@ int registerReporter(const char* name, int priority) {
template <typename Type, typename... Rest> \
struct iter<std::tuple<Type, Rest...>> \
{ \
- iter(int line, int index) { \
- DOCTEST_REGISTER_TYPED_TEST_CASE_IMPL(func<Type>, Type, dec, line * 1000 + index); \
- iter<std::tuple<Rest...>>(line, index + 1); \
+ iter(const char* file, unsigned line, int index) { \
+ doctest::detail::regTest(doctest::detail::TestCase(func<Type>, file, line, \
+ doctest_detail_test_suite_ns::getCurrentTestSuite(), \
+ doctest::detail::type_to_string<Type>(), \
+ int(line) * 1000 + index) \
+ * dec); \
+ iter<std::tuple<Rest...>>(file, line, index + 1); \
} \
}; \
template <> \
struct iter<std::tuple<>> \
{ \
- iter(int, int) {} \
+ iter(const char*, unsigned, int) {} \
}; \
} \
template <typename T> \
@@ -1953,33 +1971,22 @@ int registerReporter(const char* name, int priority) {
DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \
DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_))
-#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(id, anon, ...) \
- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = [] { \
- DOCTEST_CAT(id, ITERATOR)<std::tuple<__VA_ARGS__>> DOCTEST_UNUSED DOCTEST_CAT( \
- anon, inner_dummy)(__LINE__, 0); \
- return 0; \
- }(); \
+#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = \
+ doctest::detail::instantiationHelper(DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0));\
DOCTEST_GLOBAL_NO_WARNINGS_END()
#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
- DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-#define DOCTEST_TEST_CASE_TEMPLATE_APPLY_IMPL(id, anon, ...) \
- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = [] { \
- DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__> DOCTEST_UNUSED DOCTEST_CAT(anon, inner_dummy)( \
- __LINE__, 0); \
- return 0; \
- }(); \
- DOCTEST_GLOBAL_NO_WARNINGS_END()
-
#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
- DOCTEST_TEST_CASE_TEMPLATE_APPLY_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \
typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \
DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \
- DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(anon, anon, __VA_ARGS__) \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \
template <typename T> \
static void anon()
@@ -2508,11 +2515,11 @@ constexpr T to_lvalue = x;
#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__)
#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id)
-#define DOCTEST_GIVEN(name) SUBCASE(" Given: " name)
-#define DOCTEST_WHEN(name) SUBCASE(" When: " name)
-#define DOCTEST_AND_WHEN(name) SUBCASE("And when: " name)
-#define DOCTEST_THEN(name) SUBCASE(" Then: " name)
-#define DOCTEST_AND_THEN(name) SUBCASE(" And: " name)
+#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name)
+#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name)
+#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name)
+#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name)
+#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name)
// clang-format on
// == SHORT VERSIONS OF THE MACROS
diff --git a/examples/all_features/concurrency.cpp b/examples/all_features/concurrency.cpp
index b67403d..844ebaa 100644
--- a/examples/all_features/concurrency.cpp
+++ b/examples/all_features/concurrency.cpp
@@ -9,6 +9,8 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#include <stdexcept>
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
+DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted
+
TEST_CASE("threads...") {
auto call_from_thread = [](int value) {
INFO("print me!");
diff --git a/examples/all_features/test_output/version.txt b/examples/all_features/test_output/version.txt
index b9ec747..18ef42e 100644
--- a/examples/all_features/test_output/version.txt
+++ b/examples/all_features/test_output/version.txt
@@ -1 +1 @@
-[doctest] doctest version is "2.3.2"
+[doctest] doctest version is "2.3.3"
diff --git a/examples/all_features/test_output/version_xml.txt b/examples/all_features/test_output/version_xml.txt
index 74739c2..e738379 100644
--- a/examples/all_features/test_output/version_xml.txt
+++ b/examples/all_features/test_output/version_xml.txt
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
-<doctest binary="all_features" version="2.3.2">
+<doctest binary="all_features" version="2.3.3">
<Options order_by="file" rand_seed="324" first="0" last="4294967295" abort_after="0" subcase_filter_levels="2147483647" case_sensitive="false" no_throw="false" no_skip="false"/>
</doctest>
diff --git a/meson.build b/meson.build
index 1bb06a1..fa31e36 100644
--- a/meson.build
+++ b/meson.build
@@ -1,3 +1,2 @@
-project('doctest', ['cpp'], version: '2.3.2', meson_version:'>=0.50')
+project('doctest', ['cpp'], version: '2.3.3', meson_version:'>=0.50')
doctest_dep = declare_dependency(include_directories: include_directories('doctest'))
-
diff --git a/scripts/cmake/Config.cmake.in b/scripts/cmake/Config.cmake.in
index 6e9256e..44ddb07 100644
--- a/scripts/cmake/Config.cmake.in
+++ b/scripts/cmake/Config.cmake.in
@@ -1 +1,6 @@
-include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
+if(NOT TARGET doctest::doctest)
+ # Provide path for scripts
+ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
+
+ include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
+endif()
diff --git a/scripts/cmake/doctest.cmake b/scripts/cmake/doctest.cmake
new file mode 100644
index 0000000..c5670be
--- /dev/null
+++ b/scripts/cmake/doctest.cmake
@@ -0,0 +1,175 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+doctest
+-----
+
+This module defines a function to help use the doctest test framework.
+
+The :command:`doctest_discover_tests` discovers tests by asking the compiled test
+executable to enumerate its tests. This does not require CMake to be re-run
+when tests change. However, it may not work in a cross-compiling environment,
+and setting test properties is less convenient.
+
+This command is intended to replace use of :command:`add_test` to register
+tests, and will create a separate CTest test for each doctest test case. Note
+that this is in some cases less efficient, as common set-up and tear-down logic
+cannot be shared by multiple test cases executing in the same instance.
+However, it provides more fine-grained pass/fail information to CTest, which is
+usually considered as more beneficial. By default, the CTest test name is the
+same as the doctest name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
+
+.. command:: doctest_discover_tests
+
+ Automatically add tests with CTest by querying the compiled test executable
+ for available tests::
+
+ doctest_discover_tests(target
+ [TEST_SPEC arg1...]
+ [EXTRA_ARGS arg1...]
+ [WORKING_DIRECTORY dir]
+ [TEST_PREFIX prefix]
+ [TEST_SUFFIX suffix]
+ [PROPERTIES name1 value1...]
+ [TEST_LIST var]
+ )
+
+ ``doctest_discover_tests`` sets up a post-build command on the test executable
+ that generates the list of tests by parsing the output from running the test
+ with the ``--list-test-cases`` argument. This ensures that the full
+ list of tests is obtained. Since test discovery occurs at build time, it is
+ not necessary to re-run CMake when the list of tests changes.
+ However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set
+ in order to function in a cross-compiling environment.
+
+ Additionally, setting properties on tests is somewhat less convenient, since
+ the tests are not available at CMake time. Additional test properties may be
+ assigned to the set of tests as a whole using the ``PROPERTIES`` option. If
+ more fine-grained test control is needed, custom content may be provided
+ through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES`
+ directory property. The set of discovered tests is made accessible to such a
+ script via the ``<target>_TESTS`` variable.
+
+ The options are:
+
+ ``target``
+ Specifies the doctest executable, which must be a known CMake executable
+ target. CMake will substitute the location of the built executable when
+ running the test.
+
+ ``TEST_SPEC arg1...``
+ Specifies test cases, wildcarded test cases, tags and tag expressions to
+ pass to the doctest executable with the ``--list-test-cases`` argument.
+
+ ``EXTRA_ARGS arg1...``
+ Any extra arguments to pass on the command line to each test case.
+
+ ``WORKING_DIRECTORY dir``
+ Specifies the directory in which to run the discovered test cases. If this
+ option is not provided, the current binary directory is used.
+
+ ``TEST_PREFIX prefix``
+ Specifies a ``prefix`` to be prepended to the name of each discovered test
+ case. This can be useful when the same test executable is being used in
+ multiple calls to ``doctest_discover_tests()`` but with different
+ ``TEST_SPEC`` or ``EXTRA_ARGS``.
+
+ ``TEST_SUFFIX suffix``
+ Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of
+ every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may
+ be specified.
+
+ ``PROPERTIES name1 value1...``
+ Specifies additional properties to be set on all tests discovered by this
+ invocation of ``doctest_discover_tests``.
+
+ ``TEST_LIST var``
+ Make the list of tests available in the variable ``var``, rather than the
+ default ``<target>_TESTS``. This can be useful when the same test
+ executable is being used in multiple calls to ``doctest_discover_tests()``.
+ Note that this variable is only available in CTest.
+
+#]=======================================================================]
+
+#------------------------------------------------------------------------------
+function(doctest_discover_tests TARGET)
+ cmake_parse_arguments(
+ ""
+ ""
+ "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST"
+ "TEST_SPEC;EXTRA_ARGS;PROPERTIES"
+ ${ARGN}
+ )
+
+ if(NOT _WORKING_DIRECTORY)
+ set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+ endif()
+ if(NOT _TEST_LIST)
+ set(_TEST_LIST ${TARGET}_TESTS)
+ endif()
+
+ ## Generate a unique name based on the extra arguments
+ string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS}")
+ string(SUBSTRING ${args_hash} 0 7 args_hash)
+
+ # Define rule to generate test list for aforementioned test executable
+ set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake")
+ set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake")
+ get_property(crosscompiling_emulator
+ TARGET ${TARGET}
+ PROPERTY CROSSCOMPILING_EMULATOR
+ )
+ add_custom_command(
+ TARGET ${TARGET} POST_BUILD
+ BYPRODUCTS "${ctest_tests_file}"
+ COMMAND "${CMAKE_COMMAND}"
+ -D "TEST_TARGET=${TARGET}"
+ -D "TEST_EXECUTABLE=$<TARGET_FILE:${TARGET}>"
+ -D "TEST_EXECUTOR=${crosscompiling_emulator}"
+ -D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}"
+ -D "TEST_SPEC=${_TEST_SPEC}"
+ -D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}"
+ -D "TEST_PROPERTIES=${_PROPERTIES}"
+ -D "TEST_PREFIX=${_TEST_PREFIX}"
+ -D "TEST_SUFFIX=${_TEST_SUFFIX}"
+ -D "TEST_LIST=${_TEST_LIST}"
+ -D "CTEST_FILE=${ctest_tests_file}"
+ -P "${_DOCTEST_DISCOVER_TESTS_SCRIPT}"
+ VERBATIM
+ )
+
+ file(WRITE "${ctest_include_file}"
+ "if(EXISTS \"${ctest_tests_file}\")\n"
+ " include(\"${ctest_tests_file}\")\n"
+ "else()\n"
+ " add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n"
+ "endif()\n"
+ )
+
+ if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
+ # Add discovered tests to directory TEST_INCLUDE_FILES
+ set_property(DIRECTORY
+ APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
+ )
+ else()
+ # Add discovered tests as directory TEST_INCLUDE_FILE if possible
+ get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET)
+ if (NOT ${test_include_file_set})
+ set_property(DIRECTORY
+ PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}"
+ )
+ else()
+ message(FATAL_ERROR
+ "Cannot set more than one TEST_INCLUDE_FILE"
+ )
+ endif()
+ endif()
+
+endfunction()
+
+###############################################################################
+
+set(_DOCTEST_DISCOVER_TESTS_SCRIPT
+ ${CMAKE_CURRENT_LIST_DIR}/doctestAddTests.cmake
+)
diff --git a/scripts/cmake/doctestAddTests.cmake b/scripts/cmake/doctestAddTests.cmake
new file mode 100644
index 0000000..3df4076
--- /dev/null
+++ b/scripts/cmake/doctestAddTests.cmake
@@ -0,0 +1,81 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+set(prefix "${TEST_PREFIX}")
+set(suffix "${TEST_SUFFIX}")
+set(spec ${TEST_SPEC})
+set(extra_args ${TEST_EXTRA_ARGS})
+set(properties ${TEST_PROPERTIES})
+set(script)
+set(suite)
+set(tests)
+
+function(add_command NAME)
+ set(_args "")
+ foreach(_arg ${ARGN})
+ if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
+ set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
+ else()
+ set(_args "${_args} ${_arg}")
+ endif()
+ endforeach()
+ set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
+endfunction()
+
+# Run test executable to get list of available tests
+if(NOT EXISTS "${TEST_EXECUTABLE}")
+ message(FATAL_ERROR
+ "Specified test executable '${TEST_EXECUTABLE}' does not exist"
+ )
+endif()
+
+if("${spec}" MATCHES .)
+ set(spec "--test-case=${spec}")
+endif()
+
+execute_process(
+ COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-cases
+ OUTPUT_VARIABLE output
+ RESULT_VARIABLE result
+)
+if(NOT ${result} EQUAL 0)
+ message(FATAL_ERROR
+ "Error running test executable '${TEST_EXECUTABLE}':\n"
+ " Result: ${result}\n"
+ " Output: ${output}\n"
+ )
+endif()
+
+string(REPLACE "\n" ";" output "${output}")
+
+# Parse output
+foreach(line ${output})
+ if("${line}" STREQUAL "===============================================================================" OR "${line}" MATCHES [==[^\[doctest\] ]==])
+ continue()
+ endif()
+ set(test ${line})
+ # use escape commas to handle properly test cases with commans inside the name
+ string(REPLACE "," "\\," test_name ${test})
+ # ...and add to script
+ add_command(add_test
+ "${prefix}${test}${suffix}"
+ ${TEST_EXECUTOR}
+ "${TEST_EXECUTABLE}"
+ "--test-case=${test_name}"
+ ${extra_args}
+ )
+ add_command(set_tests_properties
+ "${prefix}${test}${suffix}"
+ PROPERTIES
+ WORKING_DIRECTORY "${TEST_WORKING_DIR}"
+ ${properties}
+ )
+ list(APPEND tests "${prefix}${test}${suffix}")
+endforeach()
+
+# Create a list of all discovered tests, which users may use to e.g. set
+# properties on the tests
+add_command(set ${TEST_LIST} ${tests})
+
+# Write CTest script
+file(WRITE "${CTEST_FILE}" "${script}")
diff --git a/scripts/coverage_maxout.cpp b/scripts/coverage_maxout.cpp
index 41118c1..6cf7ed8 100644
--- a/scripts/coverage_maxout.cpp
+++ b/scripts/coverage_maxout.cpp
@@ -19,10 +19,6 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
#ifndef DOCTEST_CONFIG_DISABLE
-namespace doctest {
-void DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS();
-}
-
// =================================================================================================
// !!! THESE ARE NOT PROPER EXAMPLES OF LIBRARY USAGE !!! THESE ARE MEANT FOR CODE COVERAGE ONLY !!!
// =================================================================================================
@@ -30,8 +26,6 @@ void DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS();
TEST_CASE("exercising tricky code paths of doctest") {
using namespace doctest;
- DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS();
-
// trigger code path for comparing the file in "operator<" of SubcaseSignature
CHECK(SubcaseSignature("", "a.cpp", 0) < SubcaseSignature("", "b.cpp", 0));
// same for String
diff --git a/scripts/release_process.md b/scripts/release_process.md
index a4240b9..691c00c 100644
--- a/scripts/release_process.md
+++ b/scripts/release_process.md
@@ -2,10 +2,12 @@
- run update_stuff.py from the scripts folder
- regenerate test output by running cmake with -DTEST_MODE=COLLECT and then running ctest
- run update_wandbox_link.py
+ - might need to do this first: set path=C:/Python27;%PATH%
- commit in dev
- merge dev in master and coverity_scan (and rebase them?)
- push all branches (git push --all)
- run update_changelog.py in master
+ - might need a tmp folder in the root drive (C or D)
- commit in master and push
- create github release with the same semver tag as the changelog
- merge master in dev
diff --git a/scripts/version.txt b/scripts/version.txt
index e703481..45674f1 100644
--- a/scripts/version.txt
+++ b/scripts/version.txt
@@ -1 +1 @@
-2.3.2 \ No newline at end of file
+2.3.3 \ No newline at end of file