The fastest feature-rich C++11/14/17/20 single-header testing framework

master branch Windows All
dev branch Windows All

doctest is a new C++ testing framework but is by far the fastest both in compile times (by orders of magnitude) and runtime compared to other feature-rich alternatives. It brings the ability of compiled languages such as D / Rust / Nim to have tests written directly in the production code thanks to a fast, transparent and flexible test runner with a clean interface.

Standard License Version download CII Best Practices Language grade: C/C++ Join the chat at https://gitter.im/onqtam/doctest Try it online

The framework is and will stay free but needs your support to sustain its development. There are lots of new features and maintenance to do. If you work for a company using doctest or have the means to do so, please consider financial support. Monthly donations via Patreon and one-offs via PayPal.

A complete example with a self-registering test that compiles to an executable looks like this:

cover-example

There are many C++ testing frameworks - Catch, Boost.Test, UnitTest++, cpputest, googletest and many other.

The key differences between it and other testing frameworks are that it is light and unintrusive:

  • Ultra light on compile times both in terms of including the header and writing thousands of asserts
  • Doesn't produce any warnings even on the most aggressive warning levels for MSVC/GCC/Clang
  • Offers a way to remove everything testing-related from the binary with the DOCTEST_CONFIG_DISABLE identifier
  • thread-safe - asserts (and logging) can be used from multiple threads spawned from a single test case - example
  • asserts can be used outside of a testing context - as a general purpose assert library - example
  • Doesn't pollute the global namespace (everything is in namespace doctest) and doesn't drag any headers with it
  • Very portable C++11 (use tag 1.2.9 for C++98) with over 180 different CI builds (static analysis, sanitizers...)
  • binaries (exe/dll) can use the test runner of another binary - so tests end up in a single registry - example

cost-of-including-the-framework-header

This allows the framework to be used in more ways than any other - tests can be written directly in the production code!

Tests can be considered a form of documentation and should be able to reside near the production code which they test.

  • This makes the barrier for writing tests much lower - you don't have to: 1) make a separate source file 2) include a bunch of stuff in it 3) add it to the build system and 4) add it to source control - You can just write the tests for a class or a piece of functionality at the bottom of its source file - or even header file!
  • Tests in the production code can be thought of as documentation or up-to-date comments - showing the use of APIs
  • Testing internals that are not exposed through the public API and headers is no longer a mind-bending exercise
  • Test-driven development in C++ has never been easier!

The framework can be used like any other if you don't want/need to mix production code and tests - check out the features.

doctest is modeled after Catch and some parts of the code have been taken directly - check out the differences.

This table compares doctest / Catch / lest which are all very similar.

Checkout the CppCon 2017 talk on YouTube to get a better understanding of how the framework works and read about how to use it in the JetBrains article - highlighting the unique aspects of the framework! On a short description on how to use the framework along production code you could refer to this GitHub issue. There is also an older article in the february edition of ACCU Overload 2017.

CppCon 2017 talk about doctest on youtube

Documentation

Project:

Usage:

Contributing

Support the development of the project with donations! There is a list of planned features which are all important and big - see the roadmap. I took a break from working in the industry to make open source software so every cent is a big deal.

If you work for a company using doctest or have the means to do so, please consider financial support.

Contributions in the form of issues and pull requests are welcome as well - check out the Contributing page.

Stargazers over time

Stargazers over time

Logo

The logo is licensed under a Creative Commons Attribution 4.0 International License. Copyright © 2019 area55git   License: CC BY 4.0

Owner
Viktor Kirilov
Working on Nimbus - an Ethereum 1.0 & 2.0 Client for Resource-Restricted Devices.
Viktor Kirilov
Comments
  • Add Github Actions CI

    Add Github Actions CI

    Opening the pull request so I can start testing the configuration. I've started by taking reproc's Github Actions configuration and removing everything reproc related. Once that works I'll start adding all doctest related configuration.

  • Regression between 2.4.6 and 2.4.7

    Regression between 2.4.6 and 2.4.7

    Description

    Following minimized code works perfectly on 2.4.6, but fails on 2.4.7

    // #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN shouldn't be defined in compilation unit to reproduce
    #include <doctest/doctest.h>
    
    #include <string>
    
    namespace {
    
    class B
    {
    public:
        const std::string& getName() const
        {
            return m_name;
        }
    
        std::string m_name = "B";
    };
    
    }  // namespace
    
    TEST_CASE("Wtf?") {
        B b;
    
        CHECK(b.getName() == "B");
    }
    

    https://godbolt.org/z/Eq48fjsed (due to the godbolt limitations see "undefined reference to `main'" linker warnings as success)

    Flags: "-std=c++11 -Wall -Wextra -Wpedantic -Werror"

    It fails on GCC version 4.9 - 10.3 with -fpermissive warning. (GCC version 11.2 compiles it without a problem though 🤔)

    doctest/doctest.h: In instantiation of 'void doctest::detail::fillstream(const T (&)[N]) [with T = char; long unsigned int N = 2]':
    doctest/doctest.h:904:31:   required from 'static void doctest::detail::filldata<T [N]>::fill(const T (&)[N]) [with T = const char; long unsigned int N = 2]'
    doctest/doctest.h:918:65:   required from 'void doctest::detail::filloss(const T (&)[N]) [with T = char; long unsigned int N = 2]'
    doctest/doctest.h:933:20:   required from 'static doctest::String doctest::detail::StringMakerBase<true>::convert(const T&) [with T = char [2]]'
    doctest/doctest.h:978:35:   required from 'doctest::String doctest::toString(const T&) [with T = char [2]; typename doctest::detail::enable_if<(! doctest::detail::is_enum<T>::value), bool>::type <anonymous> = true]'
    doctest/doctest.h:1142:45:   required from 'doctest::String doctest::detail::stringifyBinaryExpr(const L&, const char*, const R&) [with L = std::__cxx11::basic_string<char>; R = char [2]]'
    doctest/doctest.h:1320:9:   required from 'decltype (((void)((declval<L>() == declval<R>())), (doctest::detail::Result)(<brace-enclosed initializer list>()))) doctest::detail::Expression_lhs<L>::operator==(const R&) [with R = char [2]; typename doctest::detail::enable_if<(! doctest::detail::is_rvalue_reference<R>::value), void>::type* <anonymous> = 0; L = const std::__cxx11::basic_string<char>&; decltype (((void)((declval<L>() == declval<R>())), (doctest::detail::Result)(<brace-enclosed initializer list>()))) = doctest::detail::Result]'
    <source>:24:5:   required from here
    doctest/doctest.h:896:31: error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char, std::char_traits<char> >'} and 'const char')
    doctest/doctest.h:557:33: note: candidate: 'std::ostream& doctest::operator<<(std::ostream&, const doctest::String&)' (near match)
    doctest/doctest.h:557:33: note:   conversion of argument 2 would be ill-formed:
    doctest/doctest.h:896:36: error: invalid user-defined conversion from 'const char' to 'const doctest::String&' [-fpermissive]
    doctest/doctest.h:519:5: note: candidate is: 'doctest::String::String(const char*)' (near match)
    doctest/doctest.h:519:5: note:   conversion of argument 1 would be ill-formed:
    doctest/doctest.h:896:36: error: invalid conversion from 'char' to 'const char*' [-fpermissive]
    doctest/doctest.h:896:36: error: invalid conversion from 'char' to 'const char*' [-fpermissive]
    doctest/doctest.h:519:24: note:   initializing argument 1 of 'doctest::String::String(const char*)'
    In file included from /opt/compiler-explorer/gcc-10.3.0/include/c++/10.3.0/string:55,
                     from <source>:4:
    /opt/compiler-explorer/gcc-10.3.0/include/c++/10.3.0/bits/basic_string.h:6468:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&)'
     6468 |     operator<<(basic_ostream<_CharT, _Traits>& __os,
          |     ^~~~~~~~
    /opt/compiler-explorer/gcc-10.3.0/include/c++/10.3.0/bits/basic_string.h:6468:5: note:   template argument deduction/substitution failed:
    doctest/doctest.h:896:31: note:   mismatched types 'const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>' and 'const char'
    

    It fails on any version of clang, but with an error instead of the warning. It fails on MSVC at least in version 19 that is accessible on Godbolt.

    Using this code as a test, it's possible to bisect a broken commit.

  • Tests inside a static library

    Tests inside a static library

    Hi,

    (This is more a question than an issue) What is the recommended way to add tests inside a static library project ?

    If I compile a library (which includes TEST_CASE(s)) as a static library, and then I try to run the tests from this library by creating a target that links to it, the test suite is actually empty (i.e I guess the tests were stripped at link time)

    Am I doing something wrong, or is there a way to circumvent this?

    Below is an example of what I am trying to achieve (using cmake):

    Project         <- main project
      CMakeLists.txt
      doctest/
        doctest.h
        doctest_main.cpp
      MyLibrary/
        lib1.cpp    <- these files includes actual library code and TEST_CASE(s)
        lib2.cpp    
        lib3.cpp    
        CMakeLists.txt <- will produce two targets : library and its test
      MyMainProgram/
        main.cpp
        CMakeLists.txt
    
    

    MyLibrary/CMakeLists.txt :

        set(sources lib1.cpp lib2.cpp lib3.cpp)
        add_library(MyLibrary STATIC ${sources})
        target_include_directories(MyLibrary PUBLIC ${CMAKE_SOURCE_DIR}/doctest )
    
        # This does not work : it links but the test list is empty !
        add_executable(MyLibrary_DocTest ${CMAKE_SOURCE_DIR}/doctest/doctest_main.cpp)
        target_link_libraries(MyLibrary_DocTest MyLibrary)
    
        # This works, but it requires to re-compile all the source files and to re-define
        # exactly the same compile options as for the library (linked library, compile definition, etc); 
        # this can be tedious
        add_executable(MyLibrary_DocTest ${sources} ${CMAKE_SOURCE_DIR}/doctest/doctest_main.cpp)
    
    

    MyMainProgram/CMakeLists.txt :

        add_executable(MyMainProgram main.cpp)
        target_link_libraries(MyMainProgram MyLibrary)
    

    A working example can be found at https://github.com/pthom/DocTest_LibTest

  • Count points based on the number of passed/failed cases?

    Count points based on the number of passed/failed cases?

    Hi guys, I am now trying to use doctest to grade c++ code assignments, and this is my first time to use doctest. Just one question, is there any way that I can count the points based on how many testcases are passed? Or is there any way that I can perform like IF test case passed, THEN grade ++, something like that?

    Thanks a lot!

  • Doctest is not able to compile on OSX

    Doctest is not able to compile on OSX

    Description

    I am trying to get my Travis CI build working with doctest (I'm switching from Catch to this for performance), but my build is not working on OSX (It is for Linux). In my Travis CI logs, I see the following error:

    Undefined symbols for architecture x86_64:
      "std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
          doctest::String doctest::detail::stringifyBinaryExpr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, char [6]>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*, char const (&) [6]) in hello_world_test.cpp.o
    ld: symbol(s) not found for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    make[2]: *** [test/test_runner] Error 1
    make[1]: *** [test/CMakeFiles/test_runner.dir/all] Error 2
    make: *** [all] Error 2
    

    Steps to reproduce

    I'm using CMake, and my invocation command is:

    cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_COMPILER=$COMPILER -DBUILD_TESTS=ON ..
    

    (COMPILER is set to clang++ and BUILD_TYPE is set to Debug and Release, both of which fail)

    The CMake configuration I am using is (for flags):

    if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
        set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
    elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
        # ...
    endif(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    

    And the test configuration:

    set(TEST_SOURCES
        factorial_test.cpp
        hello_world_test.cpp
    )
    
    add_library(doctest INTERFACE)
    target_include_directories(doctest INTERFACE 
        "${CMAKE_SOURCE_DIR}/third_party/doctest" # Contains single header
    )
    
    add_executable(test_runner test_runner.cpp ${TEST_SOURCES})
    target_link_libraries(test_runner Project-Name-lib doctest)
    
    add_test(all_tests test_runner)
    

    Extra information

    • doctest version: v1.2.8
    • Operating System: Travis CI OSX XCode image 9.2
    • Compiler+version: AppleClang 9.0.0.9000039
  • Add default printers for enums

    Add default printers for enums

    I've added an assertion for a function returning an enum and the enum value. When the test failed I've got pretty informative failure output {?} == {?}...

    I don't intend to write a custom printer for my enum type, but still want to see readable values when a test fails. I've workaround the problem by casting to int, but I'd prefer if the library does this for me.

  • Logo Proposal for Doctest

    Logo Proposal for Doctest

    Hi, In response to your request for Logo, I am very grateful to be able to collaborate in your project.

    I need a short review about Doctest to start with the sketches. I can improve the existing one or create something totally new and different. You can tell me your suggestions.

  • [Feature] Better integration with tools (VS Code Test Adapter Extension)

    [Feature] Better integration with tools (VS Code Test Adapter Extension)

    Description

    The "Catch2 and Google Test Explorer" Extension for Visual Studio Code has experimental support for doctest. However, several tests with the same name but in different tests suites can't be run. Also, the test results can't be displayed reliably inline in the source code. This could be fixed if some additional information was available from the command line.

    Could you add the possibility to list the test suites and test cases with file names and line numbers from the command line?

    This would make it possible for the extension to work reliably and give VS Code users much better usability while using doctest.

    See: https://github.com/matepek/vscode-catch2-test-adapter/issues/143#issuecomment-566092840 And: https://github.com/matepek/vscode-catch2-test-adapter/issues/143#issuecomment-566139062

  • Slower than Catch in realistic test cases

    Slower than Catch in realistic test cases

    Hi,

    I did some benchmarking of doctest on my machine (Linux, gcc-4.9.3). I adapted a bit your Python script to work on Linux (with_gcc = 1 and removed the forced CMake generator).

    First, I can confirm that in the simple benchmark case, it is indeed faster to compile than Catch by a large margin. However, this is not a very realistic test case.

    I have modified the benchmark to generate 50 files, each with 25 test cases and each with 10 CHECK (using a variable and not two constants). Here are the results:

    Catch: 1 minute 56 seconds Doctest: 2 minutes 32 seconds

    In a realistic test case, doctest is significantly slower than Catch. I can see the same thing when I replace Catch by doctest in one of my large test case of my ETL library.

    Do you have any idea why this happen ?

    I can only guess that the overhead comes from the templates used to extract lhs and rhs or by the macros generating the test cases.

  • [PROJECT ANNOUNCEMENT] Looking for maintainers for Doctest

    [PROJECT ANNOUNCEMENT] Looking for maintainers for Doctest

    Working on doctest has taught me two very important lessons: how to prioritize and how to say no, and now it's time to apply them to my life. I can no longer maintain doctest properly and that's evident by my inactivity for the past 8 months - I haven't touched C++ professionally in almost 2 years and I've moved on to other things.

    I invite anyone interested in the development & maintenance of the framework to join the Discord server. I just moved doctest to a GitHub organization as suggested here and will add whoever is interested as a member. I'll release a version or two and will stick around for some time as people join in order to resolve any disputes and respond to questions and at some point, I'll promote the ones that have shown the most interest to admins & owners of the repository and the Discord server - I won't leave but I hope that by that time others would be able to reach consensus on contentious issues and I'll redirect any donations to the maintainers once this transition period is over.

    Doctest doesn't require too much work (unless new features are added) - mostly the occasional compiler bugfix & support in issues. The design goals of the framework should be followed - what made doctest successful is the art of saying no and keeping it light & easy to use.

    EDIT: some more info - https://github.com/doctest/doctest/issues/554#issuecomment-991190934

    Best regards, Viktor

  • Refactor stringification

    Refactor stringification

    So StringMaker and StringStream act as a pretty much completely parallel structure. This structure will be eradicated. For the first draft I have simply removed the StringMaker's body, attaching it's head to StringStream's body.

    The customization points are broken, as well as a few other features, namely raw memory stringification likely among others.

    This (hopefully) finally fixes #571 for good!

  • Consider re-running the benchmarks

    Consider re-running the benchmarks

    The benchmark page:

    https://github.com/doctest/doctest/blob/master/doc/markdown/benchmarks.md

    is by now 3 years old, perhaps more. Please consider re-running the same benchmarks (with the relevant newer versions of compilers and of catch etc.) and changing the values accordingly.

  • ```doctest_mpi``` doesn't seem to recognize ```DOCTEST_CONFIG_DISABLE```

    ```doctest_mpi``` doesn't seem to recognize ```DOCTEST_CONFIG_DISABLE```

    Description

    It seems like the doctest_mpi extension doesn't recognize DOCTEST_CONFIG_DISABLE as a flag for disabling tests. This leads to compilation errors.

    Steps to reproduce

    Consider a program like this:

    #define DOCTEST_CONFIG_IMPLEMENT
    #include<doctest/extensions/doctest_mpi.h>
    
    static int sums(const int value, MPI_Comm comm) {
          int out = value;
          MPI_Reduce(MPI_IN_PLACE, &out, 1, MPI_INT, MPI_SUM, 0, comm);
          return out;
    }
    
    MPI_TEST_CASE("sum works", 2) {
         MPI_CHECK(0, sum(5, test_comm) == 7);
         MPI_CHECK(1, sum(2, test_comm) == 7);
    }
    
    int main(int argc, char **argv) {
        doctest::mpi_init_thread(argc, argv, MPI_THREAD_MULTIPLE);
        doctest::Context ctx;
        ctx.setOption("reporters", "MpiConsoleReporter");
        ctx.setOption("reporters", "MpiFileReporter");
        ctx.setOption("force-colors", true);
        ctx.applyCommandLine(argc, argv);
        int test_result = ctx.run();
        doctest::mpi_finalize();
        return test_result;
    } 
    

    If I compile this as normal (i.e linking via a CMakeLists file) I don't get any errors. However, as soon as I set DOCTEST_CONFIG_DISBALE I get this:

    In file included from ../doctest/doctest/extensions/doctest_mpi.h:7,
                     from ../main.cpp:2:
    ../doctest/doctest/extensions/mpi_reporter.h:39:49: error: expected class-name before ‘{’ token
       39 | struct MpiFileReporter : public ConsoleReporter {
          |                                                 ^
    ../doctest/doctest/extensions/mpi_reporter.h: In constructor ‘doctest::{anonymous}::MpiFileReporter::MpiFileReporter(const doctest::ContextOptions&)’:
    ../doctest/doctest/extensions/mpi_reporter.h:43:7: error: class ‘doctest::{anonymous}::MpiFileReporter’ does not have any field named ‘ConsoleReporter’
       43 |     : ConsoleReporter(co,logfile_stream)
          |       ^~~~~~~~~~~~~~~
    ../doctest/doctest/extensions/mpi_reporter.h: At global scope:
    ../doctest/doctest/extensions/mpi_reporter.h:59:52: error: expected class-name before ‘{’ token
       59 | struct MpiConsoleReporter : public ConsoleReporter {
          |                                                    ^
    ../doctest/doctest/extensions/mpi_reporter.h:86:8: error: ‘void doctest::{anonymous}::MpiConsoleReporter::test_run_end(const doctest::TestRunStats&)’ marked ‘override’, but does not override
       86 |   void test_run_end(const TestRunStats& p) override {
          |        ^~~~~~~~~~~~
    In file included from ../doctest/doctest/extensions/doctest_mpi.h:7,
                     from ../main.cpp:2:
    ../doctest/doctest/extensions/mpi_reporter.h:150:8: error: ‘void doctest::{anonymous}::MpiConsoleReporter::test_case_end(const doctest::CurrentTestCaseStats&)’ marked ‘override’, but does not override
      150 |   void test_case_end(const CurrentTestCaseStats& st) override {
          |        ^~~~~~~~~~~~~
    ../doctest/doctest/extensions/mpi_reporter.h:230:8: error: ‘void doctest::{anonymous}::MpiConsoleReporter::log_assert(const doctest::AssertData&)’ marked ‘override’, but does not override
      230 |   void log_assert(const AssertData& rb) override {
          |        ^~~~~~~~~~
    In file included from ../doctest/doctest/extensions/doctest_mpi.h:7,
                     from ../main.cpp:2:
    ../doctest/doctest/extensions/mpi_reporter.h: In constructor ‘doctest::{anonymous}::MpiConsoleReporter::MpiConsoleReporter(const doctest::ContextOptions&)’:
    ../doctest/doctest/extensions/mpi_reporter.h:73:7: error: class ‘doctest::{anonymous}::MpiConsoleReporter’ does not have any field named ‘ConsoleReporter’
       73 |     : ConsoleReporter(co,replace_by_null_if_not_rank_0(co.cout))
          |       ^~~~~~~~~~~~~~~
    ../doctest/doctest/extensions/mpi_reporter.h: In member function ‘std::string doctest::{anonymous}::MpiConsoleReporter::file_line_to_string(const char*, int, const char*)’:
    ../doctest/doctest/extensions/mpi_reporter.h:80:9: error: ‘opt’ was not declared in this scope
       80 |     << (opt.gnu_file_line ? ":" : "(")
          |         ^~~
    ../doctest/doctest/extensions/mpi_reporter.h: In member function ‘void doctest::{anonymous}::MpiConsoleReporter::test_run_end(const doctest::TestRunStats&)’:
    ../doctest/doctest/extensions/mpi_reporter.h:87:5: error: ‘ConsoleReporter’ has not been declared
       87 |     ConsoleReporter::test_run_end(p);
          |     ^~~~~~~~~~~~~~~
    ../doctest/doctest/extensions/mpi_reporter.h:113:7: error: ‘separator_to_stream’ was not declared in this scope; did you mean ‘color_to_stream’?
      113 |       separator_to_stream();
          |       ^~~~~~~~~~~~~~~~~~~
          |       color_to_stream
    ../doctest/doctest/extensions/mpi_reporter.h:114:7: error: ‘s’ was not declared in this scope
      114 |       s << Color::Cyan << "[doctest] " << Color::None << "assertions on all processes: " << std::setw(6)
          |       ^
    In file included from ../doctest/doctest/extensions/doctest_mpi.h:7,
                     from ../main.cpp:2:
    ../doctest/doctest/extensions/mpi_reporter.h: In member function ‘void doctest::{anonymous}::MpiConsoleReporter::test_case_end(const doctest::CurrentTestCaseStats&)’:
    ../doctest/doctest/extensions/mpi_reporter.h:204:11: error: ‘separator_to_stream’ was not declared in this scope; did you mean ‘color_to_stream’?
      204 |           separator_to_stream();
          |           ^~~~~~~~~~~~~~~~~~~
          |           color_to_stream
    ../doctest/doctest/extensions/mpi_reporter.h:205:31: error: ‘tc’ was not declared in this scope; did you mean ‘tm’?
      205 |           file_line_to_stream(tc->m_file.c_str(), static_cast<int>(tc->m_line), "\n");
    
    

    Extra information

    • doctest version: Current version on master.
    • Operating System: Debian 11
    • Compiler+version: g++ (via mpicxx) 10.2.1
  • Fix SUBCASE infinite loop

    Fix SUBCASE infinite loop

    • Insert and check same hash for fullyTraversedSubcases

    Description

    Change the saved hash to match the hash later checked in the Subcase constructor. This fixes an infinite loop that I encountered with at least two different nested SUBCASEs inside a loop.

    TEST_CASE("Infinite")
    {
      for (int idx = 0; idx < 2; ++idx)
      {
          SUBCASE("A")
          {
              SUBCASE("SUB A")
              {
                  std::cout << "sub a" << std::endl;
              }
          }
          SUBCASE("B")
          {
              SUBCASE("SUB B")
              {
                  std::cout << "sub b" << std::endl;
              }
          }
      }
    }
    
  • doctest.h -- error: call of overloaded ‘log10(unsigned int)’ is ambiguous

    doctest.h -- error: call of overloaded ‘log10(unsigned int)’ is ambiguous

    Description

    Using doctest 2.4.9, as packaged with ccache, compiling with gcc on solaris (see versions below) results in:

    In file included from /export/home/briggs/ccache-4.7.1/unittest/main.cpp:27:
    /export/home/briggs/ccache-4.7.1/src/third_party/doctest.h: In member function ‘virtual void doctest::{anonymous}::ConsoleReporter::test_run_end(const doctest::TestRunStats&)’:
    /export/home/briggs/ccache-4.7.1/src/third_party/doctest.h:6191:48: error: call of overloaded ‘log10(unsigned int)’ is ambiguous
     6191 |             auto totwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters, static_cast<unsigned>(p.numAsserts))) + 1)));
          |                                           ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/math.h:24,
                     from /usr/gcc/11/include/c++/11.2.0/bits/std_abs.h:40,
                     from /usr/gcc/11/include/c++/11.2.0/cstdlib:77,
                     from /usr/gcc/11/include/c++/11.2.0/ext/string_conversions.h:41,
                     from /usr/gcc/11/include/c++/11.2.0/bits/basic_string.h:6607,
                     from /usr/gcc/11/include/c++/11.2.0/string:55,
                     from /export/home/briggs/ccache-4.7.1/src/Stat.hpp:29,
                     from /export/home/briggs/ccache-4.7.1/unittest/../src/Util.hpp:21,
                     from /export/home/briggs/ccache-4.7.1/unittest/main.cpp:19:
    /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/iso/math_iso.h:209:28: note: candidate: ‘long double std::log10(long double)’
      209 |         inline long double log10(long double __X) { return __log10l(__X); }
          |                            ^~~~~
    /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/iso/math_iso.h:170:22: note: candidate: ‘float std::log10(float)’
      170 |         inline float log10(float __X) { return __log10f(__X); }
          |                      ^~~~~
    /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/iso/math_iso.h:70:15: note: candidate: ‘double std::log10(double)’
       70 | extern double log10 __P((double));
          |               ^~~~~
    In file included from /export/home/briggs/ccache-4.7.1/unittest/main.cpp:27:
    /export/home/briggs/ccache-4.7.1/src/third_party/doctest.h:6192:49: error: call of overloaded ‘log10(unsigned int)’ is ambiguous
     6192 |             auto passwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast<unsigned>(p.numAsserts - p.numAssertsFailed))) + 1)));
          |                                            ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/math.h:24,
                     from /usr/gcc/11/include/c++/11.2.0/bits/std_abs.h:40,
                     from /usr/gcc/11/include/c++/11.2.0/cstdlib:77,
                     from /usr/gcc/11/include/c++/11.2.0/ext/string_conversions.h:41,
                     from /usr/gcc/11/include/c++/11.2.0/bits/basic_string.h:6607,
                     from /usr/gcc/11/include/c++/11.2.0/string:55,
                     from /export/home/briggs/ccache-4.7.1/src/Stat.hpp:29,
                     from /export/home/briggs/ccache-4.7.1/unittest/../src/Util.hpp:21,
                     from /export/home/briggs/ccache-4.7.1/unittest/main.cpp:19:
    /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/iso/math_iso.h:209:28: note: candidate: ‘long double std::log10(long double)’
      209 |         inline long double log10(long double __X) { return __log10l(__X); }
          |                            ^~~~~
    /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/iso/math_iso.h:170:22: note: candidate: ‘float std::log10(float)’
      170 |         inline float log10(float __X) { return __log10f(__X); }
          |                      ^~~~~
    /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/iso/math_iso.h:70:15: note: candidate: ‘double std::log10(double)’
       70 | extern double log10 __P((double));
          |               ^~~~~
    In file included from /export/home/briggs/ccache-4.7.1/unittest/main.cpp:27:
    /export/home/briggs/ccache-4.7.1/src/third_party/doctest.h:6193:49: error: call of overloaded ‘log10(unsigned int)’ is ambiguous
     6193 |             auto failwidth = int(std::ceil(log10((std::max(p.numTestCasesFailed, static_cast<unsigned>(p.numAssertsFailed))) + 1)));
          |                                            ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/math.h:24,
                     from /usr/gcc/11/include/c++/11.2.0/bits/std_abs.h:40,
                     from /usr/gcc/11/include/c++/11.2.0/cstdlib:77,
                     from /usr/gcc/11/include/c++/11.2.0/ext/string_conversions.h:41,
                     from /usr/gcc/11/include/c++/11.2.0/bits/basic_string.h:6607,
                     from /usr/gcc/11/include/c++/11.2.0/string:55,
                     from /export/home/briggs/ccache-4.7.1/src/Stat.hpp:29,
                     from /export/home/briggs/ccache-4.7.1/unittest/../src/Util.hpp:21,
                     from /export/home/briggs/ccache-4.7.1/unittest/main.cpp:19:
    /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/iso/math_iso.h:209:28: note: candidate: ‘long double std::log10(long double)’
      209 |         inline long double log10(long double __X) { return __log10l(__X); }
          |                            ^~~~~
    /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/iso/math_iso.h:170:22: note: candidate: ‘float std::log10(float)’
      170 |         inline float log10(float __X) { return __log10f(__X); }
          |                      ^~~~~
    /usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.2.0/include-fixed/iso/math_iso.h:70:15: note: candidate: ‘double std::log10(double)’
       70 | extern double log10 __P((double));
          |               ^~~~~
    

    Steps to reproduce

    For ccache 4.7.1, doing

    mkdir build && cd build && cmake --build .
    

    Extra information

    • doctest version: 2.4.9
    • Operating System: Solaris 11.4
    • Compiler+version: gcc 11.2.0

    There is indeed no log10() with an integral value argument. I believe that was introduced in C++11, and I suspect that the Solaris iso/math_iso.h predates that. While Oracle ought to fix that, it seems that a cast to float would simply avoid this dependency.

  • Doctest spams several thousands warnings with memory sanitizer

    Doctest spams several thousands warnings with memory sanitizer

    Description

    When compliing doctest with memory sanitizer,

    CXX=clang++ CXXFLAGS="-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-track-origins -Og" LDFLAGS="-fsanitize=memory" cmake .;make -j6
    

    it produce thousands of warnings when executing examples/all_features/all_features

    ==110585==WARNING: MemorySanitizer: use-of-uninitialized-value
        #0 0x55573e7a1bb9 in doctest::(anonymous namespace)::wildcmp(char const*, char const*, bool) main.cpp
        #1 0x55573e75fc7b in doctest::(anonymous namespace)::matchesAny(char const*, std::vector<doctest::String, std::allocator<doctest::String> > const&, bool, bool) main.cpp
        #2 0x55573e79270a in doctest::Context::run() (/home/rafal/test/doctest/examples/all_features/all_features+0x12770a) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #3 0x55573e79e5e8 in main (/home/rafal/test/doctest/examples/all_features/all_features+0x1335e8) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #4 0x7ffb3d635d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
        #5 0x7ffb3d635e3f in __libc_start_main csu/../csu/libc-start.c:392:3
        #6 0x55573e6c0704 in _start (/home/rafal/test/doctest/examples/all_features/all_features+0x55704) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
    
      Uninitialized value was stored to memory at
        #0 0x55573e6ee709 in __msan_memcpy (/home/rafal/test/doctest/examples/all_features/all_features+0x83709) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #1 0x55573e74ea67 in doctest::String::String(doctest::String&&) (/home/rafal/test/doctest/examples/all_features/all_features+0xe3a67) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #2 0x55573e897194 in void __gnu_cxx::new_allocator<doctest::String>::construct<doctest::String, doctest::String>(doctest::String*, doctest::String&&) (/home/rafal/test/doctest/examples/all_features/all_features+0x22c194) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #3 0x55573e89576b in void std::allocator_traits<std::allocator<doctest::String> >::construct<doctest::String, doctest::String>(std::allocator<doctest::String>&, doctest::String*, doctest::String&&) (/home/rafal/test/doctest/examples/all_features/all_features+0x22a76b) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #4 0x55573e8963ad in void std::vector<doctest::String, std::allocator<doctest::String> >::_M_realloc_insert<doctest::String>(__gnu_cxx::__normal_iterator<doctest::String*, std::vector<doctest::String, std::allocator<doctest::String> > >, doctest::String&&) (/home/rafal/test/doctest/examples/all_features/all_features+0x22b3ad) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #5 0x55573e895435 in void std::vector<doctest::String, std::allocator<doctest::String> >::emplace_back<doctest::String>(doctest::String&&) (/home/rafal/test/doctest/examples/all_features/all_features+0x22a435) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #6 0x55573e817311 in std::vector<doctest::String, std::allocator<doctest::String> >::push_back(doctest::String&&) (/home/rafal/test/doctest/examples/all_features/all_features+0x1ac311) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #7 0x55573e7a2a51 in doctest::(anonymous namespace)::parseCommaSepArgs(int, char const* const*, char const*, std::vector<doctest::String, std::allocator<doctest::String> >&)::$_2::operator()() const main.cpp
        #8 0x55573e786aad in doctest::(anonymous namespace)::parseCommaSepArgs(int, char const* const*, char const*, std::vector<doctest::String, std::allocator<doctest::String> >&) main.cpp
        #9 0x55573e7786e1 in doctest::Context::parseArgs(int, char const* const*, bool) (/home/rafal/test/doctest/examples/all_features/all_features+0x10d6e1) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #10 0x55573e7896ca in doctest::Context::setOption(char const*, char const*) (/home/rafal/test/doctest/examples/all_features/all_features+0x11e6ca) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #11 0x55573e788e0c in doctest::Context::addFilter(char const*, char const*) (/home/rafal/test/doctest/examples/all_features/all_features+0x11de0c) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #12 0x55573e79e472 in main (/home/rafal/test/doctest/examples/all_features/all_features+0x133472) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #13 0x7ffb3d635d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    
      Uninitialized value was stored to memory at
        #0 0x55573e6ee709 in __msan_memcpy (/home/rafal/test/doctest/examples/all_features/all_features+0x83709) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #1 0x55573e74c1e4 in doctest::String::String(char const*, unsigned int) (/home/rafal/test/doctest/examples/all_features/all_features+0xe11e4) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #2 0x55573e74bdd1 in doctest::String::String(char const*) (/home/rafal/test/doctest/examples/all_features/all_features+0xe0dd1) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #3 0x55573e7a2a11 in doctest::(anonymous namespace)::parseCommaSepArgs(int, char const* const*, char const*, std::vector<doctest::String, std::allocator<doctest::String> >&)::$_2::operator()() const main.cpp
        #4 0x55573e786aad in doctest::(anonymous namespace)::parseCommaSepArgs(int, char const* const*, char const*, std::vector<doctest::String, std::allocator<doctest::String> >&) main.cpp
        #5 0x55573e7786e1 in doctest::Context::parseArgs(int, char const* const*, bool) (/home/rafal/test/doctest/examples/all_features/all_features+0x10d6e1) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #6 0x55573e7896ca in doctest::Context::setOption(char const*, char const*) (/home/rafal/test/doctest/examples/all_features/all_features+0x11e6ca) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #7 0x55573e788e0c in doctest::Context::addFilter(char const*, char const*) (/home/rafal/test/doctest/examples/all_features/all_features+0x11de0c) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #8 0x55573e79e472 in main (/home/rafal/test/doctest/examples/all_features/all_features+0x133472) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #9 0x7ffb3d635d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    
      Uninitialized value was stored to memory at
        #0 0x55573e6ee709 in __msan_memcpy (/home/rafal/test/doctest/examples/all_features/all_features+0x83709) (BuildId: 3ea1d43b0b3e71f1d4967436582f7754d57a2e19)
        #1 0x7ffb3da87ee4 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace(unsigned long, unsigned long, char const*, unsigned long) (/lib/x86_64-linux-gnu/libstdc++.so.6+0x14cee4) (BuildId: f57e02bfadacc0c923c82457d5e18e1830b5faea)
    
      Uninitialized value was created by an allocation of 's' in the stack frame of function '_ZN7doctest12_GLOBAL__N_117parseCommaSepArgsEiPKPKcS2_RSt6vectorINS_6StringESaIS6_EE'
        #0 0x55573e785720 in doctest::(anonymous namespace)::parseCommaSepArgs(int, char const* const*, char const*, std::vector<doctest::String, std::allocator<doctest::String> >&) main.cpp
    
    SUMMARY: MemorySanitizer: use-of-uninitialized-value main.cpp in doctest::(anonymous namespace)::wildcmp(char const*, char const*, bool)
    
    

    Extra information

    • doctest version: Git
    • Operating System: Ubuntu 22.04
    • Compiler+version: Clang 14
  • Coverity warnings for doctest.h 2.4.9, USE_AFTER_MOVE

    Coverity warnings for doctest.h 2.4.9, USE_AFTER_MOVE

    We embed doctest.h so coverity ends up running on it. I am not bothered by those warnings, but I wanted to post it here in case this means something to doctest authors.

    • See also my previous https://github.com/doctest/doctest/issues/486
    ** CID 401622:    (USE_AFTER_MOVE)
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<unsigned long>::operator ==<int>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_config_ssl_profile_t *&>::operator ==<std::nullptr_t>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_http_connector_t *>::operator ==<std::nullptr_t>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<char (&)[128]>::operator ==<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_error_t>::operator ==<qd_error_t>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_http_listener_t *>::operator ==<std::nullptr_t>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<int>::operator ==<int>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<unsigned long &>::operator ==<int>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<char *&>::operator ==<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<const char *const &>::operator ==<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<const char *&>::operator ==<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<long>::operator ==<unsigned long>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<long>::operator ==<int>(T1 &&)()
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<char (&)[3]>::operator ==<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(T1 &&)()
    
    
    ________________________________________________________________________________________________________
    *** CID 401622:    (USE_AFTER_MOVE)
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<unsigned long>::operator ==<int>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_config_ssl_profile_t *&>::operator ==<std::nullptr_t>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_http_connector_t *>::operator ==<std::nullptr_t>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<char (&)[128]>::operator ==<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_error_t>::operator ==<qd_error_t>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_http_listener_t *>::operator ==<std::nullptr_t>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<int>::operator ==<int>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<unsigned long &>::operator ==<int>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<char *&>::operator ==<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<const char *const &>::operator ==<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<const char *&>::operator ==<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<long>::operator ==<unsigned long>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<long>::operator ==<int>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<char (&)[3]>::operator ==<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401622:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    
    *** CID 401620:    (USE_AFTER_MOVE)
    /skupper-router/tests/c_unittests/doctest.h: 1486 in doctest::detail::Expression_lhs<bool>::operator !=<const bool &>(T1 &&)()
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    >>>     CID 401620:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    1491             // clang-format on
    /skupper-router/tests/c_unittests/doctest.h: 1486 in doctest::detail::Expression_lhs<unsigned long>::operator !=<const unsigned long &>(T1 &&)()
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    >>>     CID 401620:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    1491             // clang-format on
    
    *** CID 401617:    (USE_AFTER_MOVE)
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_http_connector_t *>::operator ==<std::nullptr_t>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401617:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<int>::operator ==<unsigned long &>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401617:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<int>::operator ==<int>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401617:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<long>::operator ==<unsigned long>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401617:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_http_listener_t *>::operator ==<std::nullptr_t>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401617:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<long>::operator ==<int>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401617:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<unsigned long>::operator ==<int>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401617:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<qd_error_t>::operator ==<qd_error_t>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401617:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<bool>::operator ==<const bool &>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401617:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    /skupper-router/tests/c_unittests/doctest.h: 1485 in doctest::detail::Expression_lhs<char>::operator ==<char &>(T1 &&)()
    1479             }
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    >>>     CID 401617:    (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    
    *** CID 401615:  Uninitialized variables  (USE_AFTER_MOVE)
    /skupper-router/tests/c_unittests/doctest.h: 1490 in doctest::detail::Expression_lhs<int>::operator <=<int>(T1 &&)()
    1484             // clang-format off
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    >>>     CID 401615:  Uninitialized variables  (USE_AFTER_MOVE)
    >>>     "this->lhs" is used after it has been already moved.
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    1491             // clang-format on
    1492     
    1493             // forbidding some expressions based on this table: https://u15810271.ct.sendgrid.net/ls/click?upn=HRESupC-2F2Czv4BOaCWWCy1-2FwctJa0uG0ag06OxpLrO0j4UGRfO2kMh0WDp8VTRULL-2BkHBzZzwAhSz0821pK26d6P8vGkQtL0V3n1oGwmFq8-3DHEIW_vFj7lc-2B5eqPYQf-2FeVMiM193iHrPx7EWvtmbCR2uSfFpXFSoPvBAKzLcpp9H5lE3WAYFU-2BewzRVpPdygsC2yZTWPanX1H6LyvWzSbqz4xNObdWE6Vbh0EWcCcmgBXgYWrRfju-2F19-2FslM2gvLpBUtGSZYgO6RIPNWsoyc8sNLogj75Fp8JZP-2FdzZr6Azof4MrPYLvgih9tNNGpYOba-2F0NBKw-3D-3D
    1494             DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &)
    1495             DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^)
    
    *** CID 401613:    (USE_AFTER_MOVE)
    /skupper-router/tests/c_unittests/doctest.h: 1486 in doctest::detail::Expression_lhs<qd_config_ssl_profile_t *&>::operator !=<std::nullptr_t>(T1 &&)()
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    >>>     CID 401613:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    1491             // clang-format on
    /skupper-router/tests/c_unittests/doctest.h: 1486 in doctest::detail::Expression_lhs<_object *&>::operator !=<std::nullptr_t>(T1 &&)()
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    >>>     CID 401613:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    1491             // clang-format on
    /skupper-router/tests/c_unittests/doctest.h: 1486 in doctest::detail::Expression_lhs<qd_dispatch_t *&>::operator !=<std::nullptr_t>(T1 &&)()
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    >>>     CID 401613:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    1491             // clang-format on
    /skupper-router/tests/c_unittests/doctest.h: 1486 in doctest::detail::Expression_lhs<int &>::operator !=<int>(T1 &&)()
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    >>>     CID 401613:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    1491             // clang-format on
    /skupper-router/tests/c_unittests/doctest.h: 1486 in doctest::detail::Expression_lhs<qd_http_listener_t *&>::operator !=<std::nullptr_t>(T1 &&)()
    1480     
    1481             /* This is required for user-defined conversions from Expression_lhs to L */
    1482             operator L() const { return lhs; }
    1483     
    1484             // clang-format off
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    >>>     CID 401613:    (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    1491             // clang-format on
    
    *** CID 401611:  Uninitialized variables  (USE_AFTER_MOVE)
    /skupper-router/tests/c_unittests/doctest.h: 1490 in doctest::detail::Expression_lhs<int>::operator <=<int>(T1 &&)()
    1484             // clang-format off
    1485             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
    1486             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
    1487             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>,  " >  ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
    1488             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<,  " <  ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
    1489             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
    >>>     CID 401611:  Uninitialized variables  (USE_AFTER_MOVE)
    >>>     "rhs" is used after it has been already moved.
    1490             DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
    1491             // clang-format on
    1492     
    1493             // forbidding some expressions based on this table: https://u15810271.ct.sendgrid.net/ls/click?upn=HRESupC-2F2Czv4BOaCWWCy1-2FwctJa0uG0ag06OxpLrO0j4UGRfO2kMh0WDp8VTRULL-2BkHBzZzwAhSz0821pK26d6P8vGkQtL0V3n1oGwmFq8-3DK-5x_vFj7lc-2B5eqPYQf-2FeVMiM193iHrPx7EWvtmbCR2uSfFpXFSoPvBAKzLcpp9H5lE3WfNNwAzY1BWS5iKom1-2BDiKON2b9IoApgZ-2BUpKOef-2BfZGBeQDya6C06E7BhWwMO3b7m9rcuhMIDmXMtSTn7YXbg21jjhlBlVJIxbrjT-2BMwfO9am1RWLr1sTWpmv-2FGWsvo25DHtjIOz5glsolmuYj3Ejw-3D-3D
    1494             DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &)
    1495             DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^)
    
C++ Unit Testing Easier: A Header-only C++ unit testing framework

CUTE C++ Unit Testing Easier: A Header-only C++ unit testing framework usually available as part of the Cevelop C++ IDE (http://cevelop.com) Dependenc

Dec 26, 2022
The C Unit Testing Library on GitHub is a library designed for easy unit testing in C

The C Unit Testing Library on GitHub is a library designed for easy unit testing in C. It was written by Brennan Hurst for the purpose of providing a J-Unit-like testing framework within C for personal projects.

Oct 11, 2021
A complete unit testing framework in a header

liblittletest A complete unit testing framework in a header liblittletest is an easy to use all-in-an-header testing framework; all you have to do in

Nov 11, 2021
A modern, C++11-native, single-file header-only, tiny framework for unit-tests, TDD and BDD (includes C++98 variant)

lest – lest errors escape testing This tiny C++11 test framework is based on ideas and examples by Kevlin Henney [1,2] and on ideas found in the CATCH

Dec 28, 2022
Upp11 - C++11 lightweight single header unit test framework

upp11 Lightweight C++11 single header unit test framework To use framework: Copy upp11.h in you project dir. Create unit test source files or modify e

Apr 4, 2019
Header-only C++11 library for property-based testing.

autocheck Header-only C++11 library for QuickCheck (and later, SmallCheck) testing. Please consult the wiki for documentation. Install conan remote ad

Dec 22, 2022
Googletest - Google Testing and Mocking Framework

GoogleTest OSS Builds Status Announcements Release 1.10.x Release 1.10.x is now available. Coming Soon Post 1.10.x googletest will follow Abseil Live

Jan 9, 2023
C++ xUnit-like testing framework without macros

tst C++ testing framework. Installation, documentation, tutorials See WiKi. Features xUnit-like concepts minimal use of preprocessor macros declarativ

Sep 26, 2022
c++ testing framework

iutest iutest - iris unit test framework Welcome to the iutest iutest is framework for writing C++ tests. Features An XUnit test framework. Header onl

Sep 12, 2022
UT: C++20 μ(micro)/Unit Testing Framework
UT: C++20 μ(micro)/Unit Testing Framework

"If you liked it then you "should have put a"_test on it", Beyonce rule UT / μt | Motivation | Quick Start | Overview | Tutorial | Examples | User Gui

Jan 3, 2023
Modern c++17 unit testing framework on Microsoft Windows, Apple macOS, Linux, iOS and android.
Modern c++17 unit testing framework on Microsoft Windows, Apple macOS, Linux, iOS and android.

tunit Modern c++17 unit testing framework on Windows, macOS, Linux, iOS and android. Continuous Integration build status Operating system Status Windo

Apr 5, 2022
Simple C testing framework

MrTest Simple C testing framework Usage Copy the mrtest.c and mrtest.h file into your project. In order to use the mrtest main: create a .c file that

Jul 20, 2022
xtest is a C++ testing framework inspired by googletest.
xtest is a C++ testing framework inspired by googletest.

xtest C++ testing framework inspired by googletest Explore the docs » Wiki · Report Bug · Request Feature Contents xtest Commence Prerequisites Ubuntu

Dec 13, 2022
A minimal testing framework for C/C++
A minimal testing framework for C/C++

mtest About mtest is a minimal testing framework for C++. Requirements Windows or UNIX-like host A compiler supporting C++11 Usage To include mtest in

Jan 10, 2022
Kernel-mode C++ unit testing framework in BDD-style

There is a lack of unit testing frameworks that work in OS kernel. This library closes that gap and is targeted for windows driver developers.

Dec 28, 2022
Simple, fast, accurate single-header microbenchmarking functionality for C++11/14/17/20

ankerl::nanobench ankerl::nanobench is a platform independent microbenchmarking library for C++11/14/17/20. #includ

Dec 25, 2022
Practical mutation testing tool for C and C++

Mull Mull is a tool for Mutation Testing based on LLVM/Clang with a strong focus on C and C++ languages. For installation and usage please refer to th

Dec 30, 2022
proftest is a C application for testing the quality of different operating system APIs for profiling.

proftest is a C application for testing the quality of different operating system APIs for profiling.

Jul 23, 2021
A micro unit-testing library for C/C++

µ-test A micro unit testing framework for C/C++ to get you up and running with unit-testing ASAP (even without libc). Usage Simply include the C and h

Dec 8, 2021