diff options
author | Didier Raboud <odyx@debian.org> | 2019-06-21 16:42:11 +0200 |
---|---|---|
committer | Didier Raboud <odyx@debian.org> | 2019-06-21 16:42:11 +0200 |
commit | 0dcd87acca6a8134f9ef0f2ccf9d14b792cd055e (patch) | |
tree | 634dc3c06af123d82ef0b16a9f9a82667a1b3137 | |
parent | 873e4e3f3119c022f1295c9e701b3246b8971c15 (diff) | |
parent | b23c9f8f404d86ab14c3a6e7c1a2229578bb6373 (diff) |
record new upstream branch and merge it
-rw-r--r-- | .travis.yml | 19 | ||||
-rw-r--r-- | CHANGELOG.md | 20 | ||||
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | appveyor.yml | 1 | ||||
-rw-r--r-- | debian/.git-dpm | 14 | ||||
-rw-r--r-- | doc/markdown/build-systems.md | 2 | ||||
-rw-r--r-- | doc/markdown/features.md | 1 | ||||
-rw-r--r-- | doc/markdown/roadmap.md | 1 | ||||
-rw-r--r-- | doctest/doctest.h | 190 | ||||
-rw-r--r-- | doctest/parts/doctest.cpp | 105 | ||||
-rw-r--r-- | doctest/parts/doctest_fwd.h | 85 | ||||
-rw-r--r-- | examples/all_features/concurrency.cpp | 2 | ||||
-rw-r--r-- | examples/all_features/test_output/version.txt | 2 | ||||
-rw-r--r-- | examples/all_features/test_output/version_xml.txt | 2 | ||||
-rw-r--r-- | meson.build | 3 | ||||
-rw-r--r-- | scripts/cmake/Config.cmake.in | 7 | ||||
-rw-r--r-- | scripts/cmake/doctest.cmake | 175 | ||||
-rw-r--r-- | scripts/cmake/doctestAddTests.cmake | 81 | ||||
-rw-r--r-- | scripts/coverage_maxout.cpp | 6 | ||||
-rw-r--r-- | scripts/release_process.md | 2 | ||||
-rw-r--r-- | scripts/version.txt | 2 |
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}" @@ -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 |