Migrate from Catch to Doctest

This reduces the build times of the test suite by about two thirds in my
testing in another project.

Change-Id: I8a5da3aff0956796c718d13237d0620f48316029
Depends-on: https://gerrit.cesnet.cz/c/CzechLight/dependencies/+/1580
diff --git a/.clang-format b/.clang-format
index f9b078b..2a60aa0 100644
--- a/.clang-format
+++ b/.clang-format
@@ -4,7 +4,7 @@
 Standard: Cpp11
 Cpp11BracedListStyle: true
 IncludeCategories:
-  - Regex: '^"trompeloeil_catch.h'
+  - Regex: '^"trompeloeil_doctest.h'
     Priority:        1
   - Regex:           '^<'
     Priority:        2
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1289ac4..cd22deb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -128,16 +128,16 @@
 if(BUILD_TESTING)
     enable_testing()
     find_package(trompeloeil 33 REQUIRED)
-    find_package(Catch2 2.7.0 REQUIRED)
+    find_package(doctest 2.3.1 REQUIRED)
 
-    add_library(TestCatchIntegration STATIC
-        tests/catch_integration.cpp
-        tests/trompeloeil_catch.h
+    add_library(DoctestIntegration STATIC
+        tests/doctest_integration.cpp
+        tests/trompeloeil_doctest.h
         tests/wait-a-bit-longer.cpp
         )
-    target_include_directories(TestCatchIntegration PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/tests/ ${CMAKE_CURRENT_SOURCE_DIR}/src/)
-    target_link_libraries(TestCatchIntegration Catch2::Catch2 trompeloeil spdlog::spdlog)
-    target_compile_definitions(TestCatchIntegration PUBLIC CATCH_CONFIG_FAST_COMPILE)
+    target_include_directories(DoctestIntegration PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/tests/ ${CMAKE_CURRENT_SOURCE_DIR}/src/)
+    target_link_libraries(DoctestIntegration doctest::doctest trompeloeil spdlog::spdlog)
+    target_compile_definitions(DoctestIntegration PUBLIC DOCTEST_CONFIG_SUPER_FAST_ASSERTS)
 
     if (NOT SYSREPOCTL_EXECUTABLE)
         find_program(SYSREPOCTL_EXECUTABLE sysrepoctl)
@@ -153,12 +153,12 @@
         add_executable(test_${fname}
             tests/${fname}.cpp
             )
-        target_link_libraries(test_${fname} TestCatchIntegration parser)
+        target_link_libraries(test_${fname} DoctestIntegration parser)
         if(NOT CMAKE_CROSSCOMPILING)
             add_test(test_${fname} test_${fname})
         endif()
         target_include_directories(test_${fname} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
-        target_link_libraries(test_${fname} TestCatchIntegration)
+        target_link_libraries(test_${fname} DoctestIntegration)
     endfunction()
     cli_test(cd)
     cli_test(ls)
diff --git a/submodules/dependencies b/submodules/dependencies
index 0223a86..9302fc0 160000
--- a/submodules/dependencies
+++ b/submodules/dependencies
@@ -1 +1 @@
-Subproject commit 0223a864791f7acd8121c834689d5517bd420275
+Subproject commit 9302fc0e7cdeaa8ad8feee3246f3a1ba58d284ec
diff --git a/tests/catch_integration.cpp b/tests/catch_integration.cpp
deleted file mode 100644
index e1b18db..0000000
--- a/tests/catch_integration.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#define CATCH_CONFIG_MAIN
-#include <catch2/catch.hpp>
-#include <sstream>
-#include <trompeloeil.hpp>
-
-namespace trompeloeil
-  {
-    template <>
-    void reporter<specialized>::send(
-      severity s,
-      const char* file,
-      unsigned long line,
-      const char* msg)
-    {
-      std::ostringstream os;
-      if (line) os << file << ':' << line << '\n';
-      os << msg;
-      auto failure = os.str();
-      if (s == severity::fatal)
-      {
-        FAIL(failure);
-      }
-      else
-      {
-        CAPTURE(failure);
-        CHECK(failure.empty());
-      }
-    }
-  }
diff --git a/tests/cd.cpp b/tests/cd.cpp
index 44d87dd..45e7bec 100644
--- a/tests/cd.cpp
+++ b/tests/cd.cpp
@@ -6,7 +6,7 @@
  *
 */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 #include "ast_commands.hpp"
 #include "parser.hpp"
 #include "static_schema.hpp"
diff --git a/tests/command_completion.cpp b/tests/command_completion.cpp
index 83ade0a..015b4db 100644
--- a/tests/command_completion.cpp
+++ b/tests/command_completion.cpp
@@ -6,7 +6,7 @@
  *
 */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 #include "parser.hpp"
 #include "static_schema.hpp"
 
diff --git a/tests/doctest_integration.cpp b/tests/doctest_integration.cpp
new file mode 100644
index 0000000..b333b7d
--- /dev/null
+++ b/tests/doctest_integration.cpp
@@ -0,0 +1,24 @@
+#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+#include <doctest/doctest.h>
+#include <trompeloeil.hpp>
+
+namespace trompeloeil
+{
+  template <>
+  void reporter<specialized>::send(
+    severity s,
+    const char* file,
+    unsigned long line,
+    const char* msg)
+  {
+    auto f = line ? file : "[file/line unavailable]";
+    if (s == severity::fatal)
+    {
+      ADD_FAIL_AT(f, line, msg);
+    }
+    else
+    {
+      ADD_FAIL_CHECK_AT(f, line, msg);
+    }
+  }
+}
diff --git a/tests/enum_completion.cpp b/tests/enum_completion.cpp
index e352c7f..5cb5744 100644
--- a/tests/enum_completion.cpp
+++ b/tests/enum_completion.cpp
@@ -7,7 +7,7 @@
  *
  */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 #include "ast_commands.hpp"
 #include "parser.hpp"
 #include "static_schema.hpp"
diff --git a/tests/leaf_editing.cpp b/tests/leaf_editing.cpp
index f18af1c..4fdafa0 100644
--- a/tests/leaf_editing.cpp
+++ b/tests/leaf_editing.cpp
@@ -6,7 +6,7 @@
  *
 */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 #include "ast_commands.hpp"
 #include "parser.hpp"
 #include "static_schema.hpp"
diff --git a/tests/list_manipulation.cpp b/tests/list_manipulation.cpp
index 2cc267d..717ce3a 100644
--- a/tests/list_manipulation.cpp
+++ b/tests/list_manipulation.cpp
@@ -5,7 +5,7 @@
  *
 */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 #include "parser.hpp"
 #include "static_schema.hpp"
 
diff --git a/tests/ls.cpp b/tests/ls.cpp
index 60e4b43..d56df29 100644
--- a/tests/ls.cpp
+++ b/tests/ls.cpp
@@ -6,7 +6,7 @@
  *
 */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 #include "ast_commands.hpp"
 #include "parser.hpp"
 #include "static_schema.hpp"
diff --git a/tests/path_completion.cpp b/tests/path_completion.cpp
index e0faf15..462a2e6 100644
--- a/tests/path_completion.cpp
+++ b/tests/path_completion.cpp
@@ -6,7 +6,7 @@
  *
 */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 #include "ast_commands.hpp"
 #include "parser.hpp"
 #include "static_schema.hpp"
diff --git a/tests/presence_containers.cpp b/tests/presence_containers.cpp
index 91b3e95..e027fb9 100644
--- a/tests/presence_containers.cpp
+++ b/tests/presence_containers.cpp
@@ -7,7 +7,7 @@
  *
 */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 #include "ast_commands.hpp"
 #include "parser.hpp"
 #include "static_schema.hpp"
diff --git a/tests/sysrepo.cpp b/tests/sysrepo.cpp
index a0e791a..1803890 100644
--- a/tests/sysrepo.cpp
+++ b/tests/sysrepo.cpp
@@ -6,7 +6,7 @@
  *
 */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 
 #include "sysrepo_access.hpp"
 #include "sysrepo_subscription.hpp"
diff --git a/tests/trompeloeil_catch.h b/tests/trompeloeil_catch.h
deleted file mode 100644
index 3de799b..0000000
--- a/tests/trompeloeil_catch.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-
-#include <catch2/catch.hpp>
-#include <trompeloeil.hpp>
-
-extern template struct trompeloeil::reporter<trompeloeil::specialized>;
-
-void waitForCompletionAndBitMore(const trompeloeil::sequence& seq);
diff --git a/tests/trompeloeil_doctest.h b/tests/trompeloeil_doctest.h
new file mode 100644
index 0000000..8ee4071
--- /dev/null
+++ b/tests/trompeloeil_doctest.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <doctest/doctest.h>
+#include <trompeloeil.hpp>
+
+#define SECTION(name) DOCTEST_SUBCASE(name)
+
+// https://github.com/onqtam/doctest/issues/216
+#undef REQUIRE_THROWS
+#undef REQUIRE_THROWS_AS
+#undef REQUIRE_THROWS_WITH
+#undef REQUIRE_NOTHROW
+#define REQUIRE_THROWS(expr) DOCTEST_REQUIRE_THROWS(static_cast<void>(expr))
+#define REQUIRE_THROWS_AS(expr, e) DOCTEST_REQUIRE_THROWS_AS(static_cast<void>(expr), e)
+#define REQUIRE_THROWS_WITH(expr, e) DOCTEST_REQUIRE_THROWS_WITH(static_cast<void>(expr), e)
+#define REQUIRE_NOTHROW(expr) DOCTEST_REQUIRE_NOTHROW(static_cast<void>(expr))
+
+extern template struct trompeloeil::reporter<trompeloeil::specialized>;
+
+void waitForCompletionAndBitMore(const trompeloeil::sequence& seq);
diff --git a/tests/utils.cpp b/tests/utils.cpp
index e24b0d5..a6a982b 100644
--- a/tests/utils.cpp
+++ b/tests/utils.cpp
@@ -6,7 +6,7 @@
  *
 */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 #include "utils.hpp"
 
 TEST_CASE("utils")
diff --git a/tests/wait-a-bit-longer.cpp b/tests/wait-a-bit-longer.cpp
index 029e36f..8ec4f4b 100644
--- a/tests/wait-a-bit-longer.cpp
+++ b/tests/wait-a-bit-longer.cpp
@@ -1,4 +1,4 @@
-#include <catch2/catch.hpp>
+#include <doctest/doctest.h>
 #include <chrono>
 #include <thread>
 #include <trompeloeil.hpp>
diff --git a/tests/yang.cpp b/tests/yang.cpp
index 5846a23..b4bec48 100644
--- a/tests/yang.cpp
+++ b/tests/yang.cpp
@@ -6,7 +6,7 @@
  *
 */
 
-#include "trompeloeil_catch.h"
+#include "trompeloeil_doctest.h"
 #include "yang_schema.hpp"
 
 const char* second_schema = R"(