diff --git a/.clang-format-include b/.clang-format-include index 838e22f1..bf95d83d 100644 --- a/.clang-format-include +++ b/.clang-format-include @@ -6,5 +6,4 @@ + src/**/*.h + tests/**/*.cc + tests/**/*.h -+ tests/**/*.cppm -- tests/catch.h ++ tests/**/*.cppm \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f6a9841a..f690f761 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,8 @@ cmake_minimum_required(VERSION 3.16) # project(clang-uml C CXX) +cmake_policy(SET CMP0054 NEW) + # # CMake standard defines # diff --git a/README.md b/README.md index 9b663852..8514cbfe 100644 --- a/README.md +++ b/README.md @@ -447,7 +447,7 @@ This project relies on the following great tools: * [Clang LibTooling](https://clang.llvm.org/docs/LibTooling.html) - a C++ library for creating tools based on Clang * [PlantUML](https://plantuml.com/) - language and diagram for generating UML diagrams * [MermaidJS](https://mermaid.js.org/) - JavaScript based diagramming and charting tool -* [Catch2](https://github.com/catchorg/Catch2) - C++ unit test framework +* [doctest](https://github.com/doctest/doctest) - C++ unit test framework * [glob](https://github.com/p-ranav/glob) - Unix style path expansion for C++ * [indicators](https://github.com/p-ranav/indicators) - Activity indicators for modern C++ * [CLI11](https://github.com/CLIUtils/CLI11) - command line parser for C++ diff --git a/docs/test_cases/t00002.md b/docs/test_cases/t00002.md index 0ae380e7..dfad9b8e 100644 --- a/docs/test_cases/t00002.md +++ b/docs/test_cases/t00002.md @@ -158,6 +158,7 @@ private: "raw": "/// Abstract foo_a", "text": "\n Abstract foo_a\n" }, + "display_name": "foo_a", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -180,6 +181,7 @@ private: "line": 10, "translation_unit": "t00002.cc" }, + "template_parameters": [], "type": "void" }, { @@ -192,6 +194,7 @@ private: "raw": "/// Abstract foo_c", "text": "\n Abstract foo_c\n" }, + "display_name": "foo_c", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -214,6 +217,7 @@ private: "line": 12, "translation_unit": "t00002.cc" }, + "template_parameters": [], "type": "void" } ], @@ -259,6 +263,7 @@ private: "methods": [ { "access": "public", + "display_name": "foo_a", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -281,6 +286,7 @@ private: "line": 18, "translation_unit": "t00002.cc" }, + "template_parameters": [], "type": "void" } ], @@ -335,6 +341,7 @@ private: "raw": "/// Do nothing unless override is provided", "text": "\n Do nothing unless override is provided\n" }, + "display_name": "foo_c", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -357,6 +364,7 @@ private: "line": 30, "translation_unit": "t00002.cc" }, + "template_parameters": [], "type": "void" } ], @@ -434,6 +442,7 @@ private: "raw": "/**\n * Forward foo_a\n */", "text": "\n Forward foo_a\n" }, + "display_name": "foo_a", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -456,6 +465,7 @@ private: "line": 41, "translation_unit": "t00002.cc" }, + "template_parameters": [], "type": "void" }, { @@ -468,6 +478,7 @@ private: "raw": "/**\n * Forward foo_c\n */", "text": "\n Forward foo_c\n" }, + "display_name": "foo_c", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -490,6 +501,7 @@ private: "line": 50, "translation_unit": "t00002.cc" }, + "template_parameters": [], "type": "void" } ], @@ -559,6 +571,7 @@ private: "raw": "///\n /// Forward foo_a\n ///", "text": "\n Forward foo_a\n" }, + "display_name": "foo_a", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -581,6 +594,7 @@ private: "line": 66, "translation_unit": "t00002.cc" }, + "template_parameters": [], "type": "void" }, { @@ -593,6 +607,7 @@ private: "raw": "///\n /// Forward foo_c\n ///", "text": "\n Forward foo_c\n" }, + "display_name": "foo_c", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -615,6 +630,7 @@ private: "line": 75, "translation_unit": "t00002.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00002_class.svg b/docs/test_cases/t00002_class.svg index a09ec620..8dd7045b 100644 --- a/docs/test_cases/t00002_class.svg +++ b/docs/test_cases/t00002_class.svg @@ -1,6 +1,6 @@ - + @@ -10,123 +10,123 @@ Basic class diagram example - - + + A - + - + foo_a() = 0 : void - + - + foo_c() = 0 : void - - + + B - + - + foo_a() : void - - + + C - + - + foo_c() : void - - + + D - + - + foo_a() : void - + - + foo_c() : void - + - + as : std::vector<A *> - - + + E - + - + foo_a() : void - + - + foo_c() : void - + - + as : std::vector<A *> - + This is class A - + This is class B - + This is class D diff --git a/docs/test_cases/t00002_class_mermaid.svg b/docs/test_cases/t00002_class_mermaid.svg index 69ce7e53..effd0756 100644 --- a/docs/test_cases/t00002_class_mermaid.svg +++ b/docs/test_cases/t00002_class_mermaid.svg @@ -169,7 +169,7 @@ - + @@ -198,7 +198,7 @@ - + @@ -222,7 +222,7 @@ - + @@ -246,7 +246,7 @@ - + @@ -280,7 +280,7 @@ - + diff --git a/docs/test_cases/t00003.md b/docs/test_cases/t00003.md index 1814dcc7..7bcc4ba5 100644 --- a/docs/test_cases/t00003.md +++ b/docs/test_cases/t00003.md @@ -235,6 +235,7 @@ int A::static_int = 1; "methods": [ { "access": "public", + "display_name": "A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -257,10 +258,12 @@ int A::static_int = 1; "line": 9, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -288,10 +291,12 @@ int A::static_int = 1; "line": 10, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -319,10 +324,12 @@ int A::static_int = 1; "line": 21, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -350,10 +357,12 @@ int A::static_int = 1; "line": 22, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "~A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -376,10 +385,12 @@ int A::static_int = 1; "line": 23, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "basic_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -402,10 +413,12 @@ int A::static_int = 1; "line": 25, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "static_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -428,10 +441,12 @@ int A::static_int = 1; "line": 26, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "const_method", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -454,10 +469,12 @@ int A::static_int = 1; "line": 27, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "auto_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -480,10 +497,12 @@ int A::static_int = 1; "line": 28, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "operator++", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -506,10 +525,12 @@ int A::static_int = 1; "line": 30, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "A &" }, { "access": "public", + "display_name": "operator=", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -537,10 +558,12 @@ int A::static_int = 1; "line": 36, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "A &" }, { "access": "public", + "display_name": "operator=", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -568,10 +591,12 @@ int A::static_int = 1; "line": 37, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "A &" }, { "access": "public", + "display_name": "size", "is_const": true, "is_consteval": false, "is_constexpr": true, @@ -594,10 +619,12 @@ int A::static_int = 1; "line": 39, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "std::size_t" }, { "access": "public", + "display_name": "double_int", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -625,10 +652,12 @@ int A::static_int = 1; "line": 41, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "sum", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -660,10 +689,12 @@ int A::static_int = 1; "line": 42, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "default_int", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -692,10 +723,12 @@ int A::static_int = 1; "line": 44, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "default_string", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -728,10 +761,12 @@ int A::static_int = 1; "line": 45, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "std::string" }, { "access": "public", + "display_name": "create_from_int", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -759,10 +794,12 @@ int A::static_int = 1; "line": 50, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "A" }, { "access": "protected", + "display_name": "protected_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -785,10 +822,12 @@ int A::static_int = 1; "line": 58, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "void" }, { "access": "private", + "display_name": "private_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -811,10 +850,12 @@ int A::static_int = 1; "line": 67, "translation_unit": "t00003.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -836,6 +877,14 @@ int A::static_int = 1; "type": "T" } ], + "template_parameters": [ + { + "is_variadic": false, + "kind": "template_type", + "name": "T", + "template_parameters": [] + } + ], "type": "void" } ], diff --git a/docs/test_cases/t00003_class.svg b/docs/test_cases/t00003_class.svg index de26cbfe..8bfe1080 100644 --- a/docs/test_cases/t00003_class.svg +++ b/docs/test_cases/t00003_class.svg @@ -1,6 +1,6 @@ - + @@ -9,227 +9,227 @@ - - + + A - + - + A() = default : void - + - + A(int i) : void - + - + A(A &&) = default : void - + - + A(const A &) = deleted : void A<T>(T t) : void - + - + ~A() = default : void - + - + operator=(A && other) noexcept : A & - + - + operator=(A & other) noexcept : A & - + - + operator++() : A & - + - + auto_method() : int - + - + basic_method() : void - + - + const_method() const : void - + - + create_from_int(int i) : A - + - + default_int(int i = 12) : int - + - + default_string(int i, std::string s = "abc") : std::string - + - + double_int(const int i) : int - + - + private_method() : void - + - + protected_method() : void - + - + size() constexpr const : std::size_t - + - + static_method() : int - + - + sum(const double a, const double b) : int - + - + a_ : int - + - + auto_member : const unsigned long - + - + b_ : int - + - + c_ : int - + - + compare : std::function<bool (const int)> - + - + private_member : int - + - + protected_member : int - + - + public_member : int - + - + static_const_int : const int - + - + static_int : int diff --git a/docs/test_cases/t00003_class_mermaid.svg b/docs/test_cases/t00003_class_mermaid.svg index a5041f0d..57dd570b 100644 --- a/docs/test_cases/t00003_class_mermaid.svg +++ b/docs/test_cases/t00003_class_mermaid.svg @@ -52,7 +52,7 @@ - + diff --git a/docs/test_cases/t00004.md b/docs/test_cases/t00004.md index 3eb44170..1d3810a3 100644 --- a/docs/test_cases/t00004.md +++ b/docs/test_cases/t00004.md @@ -132,6 +132,7 @@ public: "methods": [ { "access": "public", + "display_name": "foo", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -154,10 +155,12 @@ public: "line": 11, "translation_unit": "t00004.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "foo2", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -180,6 +183,7 @@ public: "line": 20, "translation_unit": "t00004.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00004_class.svg b/docs/test_cases/t00004_class.svg index 85932fd5..4f19710b 100644 --- a/docs/test_cases/t00004_class.svg +++ b/docs/test_cases/t00004_class.svg @@ -1,6 +1,6 @@ - + @@ -9,16 +9,16 @@ - - + + B - - + + B::AA @@ -28,38 +28,38 @@ AA_3 - - + + A - + - + foo() const : void - + - + foo2() const : void - - + + A::AA - - + + A::AA::Lights @@ -69,16 +69,16 @@ Red - - + + A::AA::AAA - - + + C::B @@ -87,8 +87,8 @@ - - + + C @@ -97,38 +97,38 @@ - + - + b_int : B<int> - + - + t : T - - + + C::AA - - + + C::AA::AAA - - + + C::AA::CCC @@ -137,8 +137,8 @@ CCC_2 - - + + C::B @@ -147,15 +147,15 @@ - + - + b : V - - + + C::CC @@ -164,16 +164,16 @@ CC_2 - - + + detail::D - - + + detail::D::AA @@ -183,8 +183,8 @@ AA_3 - - + + detail::D::DD diff --git a/docs/test_cases/t00004_class_mermaid.svg b/docs/test_cases/t00004_class_mermaid.svg index 68d31612..0e47dd2b 100644 --- a/docs/test_cases/t00004_class_mermaid.svg +++ b/docs/test_cases/t00004_class_mermaid.svg @@ -210,7 +210,7 @@ - + @@ -229,7 +229,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -292,7 +292,7 @@ - + @@ -311,7 +311,7 @@ - + @@ -345,7 +345,7 @@ - + @@ -364,7 +364,7 @@ - + @@ -383,7 +383,7 @@ - + @@ -412,7 +412,7 @@ - + @@ -431,7 +431,7 @@ - + @@ -450,7 +450,7 @@ - + @@ -479,7 +479,7 @@ - + @@ -503,7 +503,7 @@ - + @@ -532,7 +532,7 @@ - + @@ -551,7 +551,7 @@ - + @@ -585,7 +585,7 @@ - + diff --git a/docs/test_cases/t00005_class.svg b/docs/test_cases/t00005_class.svg index b2f7bd99..20c2d9c6 100644 --- a/docs/test_cases/t00005_class.svg +++ b/docs/test_cases/t00005_class.svg @@ -1,6 +1,6 @@ - + @@ -9,205 +9,205 @@ - - + + A - - + + B - - + + C - - + + D - - + + E - - + + F - - + + G - - + + H - - + + I - - + + J - - + + K - - + + R - + - + a : A - + - + b : B * - + - + c : C & - + - + d : const D * - + - + e : const E & - + - + f : F && - + - + g : G ** - + - + h : H *** - + - + i : I *& - + - + j : volatile J * - + - + k : K * - + - + some_int : int - + - + some_int_pointer : int * - + - + some_int_pointer_pointer : int ** - + - + some_int_reference : int & diff --git a/docs/test_cases/t00005_class_mermaid.svg b/docs/test_cases/t00005_class_mermaid.svg index 459bd244..19bc7a46 100644 --- a/docs/test_cases/t00005_class_mermaid.svg +++ b/docs/test_cases/t00005_class_mermaid.svg @@ -186,7 +186,7 @@ - + @@ -205,7 +205,7 @@ - + @@ -224,7 +224,7 @@ - + @@ -243,7 +243,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -281,7 +281,7 @@ - + @@ -300,7 +300,7 @@ - + @@ -319,7 +319,7 @@ - + @@ -338,7 +338,7 @@ - + @@ -357,7 +357,7 @@ - + @@ -376,7 +376,7 @@ - + @@ -395,7 +395,7 @@ - + diff --git a/docs/test_cases/t00006.md b/docs/test_cases/t00006.md index 3d1aa118..414512cc 100644 --- a/docs/test_cases/t00006.md +++ b/docs/test_cases/t00006.md @@ -512,7 +512,7 @@ public: "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00006::E" + "type": "E" } ], "type": "class" diff --git a/docs/test_cases/t00006_class.svg b/docs/test_cases/t00006_class.svg index 3c237c79..cb753532 100644 --- a/docs/test_cases/t00006_class.svg +++ b/docs/test_cases/t00006_class.svg @@ -1,6 +1,6 @@ - + @@ -9,136 +9,136 @@ - - + + A - - + + B - - + + C - - + + D - - + + E - - + + F - - + + G - - + + H - - + + I - - + + J - - + + K - - + + L - - + + M - - + + N - - + + NN - - + + NNN - - + + custom_container @@ -147,15 +147,15 @@ - + - + data : std::vector<T> - - + + custom_container @@ -164,103 +164,103 @@ - - + + R - + - + a : std::vector<A> - + - + b : std::vector<B *> - + - + c : std::map<int,C> - + - + d : std::map<int,D *> - + - + e : custom_container<E> - + - + f : std::vector<std::vector<F>> - + - + g : std::map<int,std::vector<G *>> - + - + h : std::array<H,10> - + - + i : std::array<I *,5> - + - + j : J[10] - + - + k : K *[20] - + - + lm : std::vector<std::pair<L,M>> - + - + ns : std::tuple<N,NN,NNN> diff --git a/docs/test_cases/t00006_class_mermaid.svg b/docs/test_cases/t00006_class_mermaid.svg index daebdb33..534cfe21 100644 --- a/docs/test_cases/t00006_class_mermaid.svg +++ b/docs/test_cases/t00006_class_mermaid.svg @@ -270,7 +270,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -308,7 +308,7 @@ - + @@ -327,7 +327,7 @@ - + @@ -346,7 +346,7 @@ - + @@ -365,7 +365,7 @@ - + @@ -384,7 +384,7 @@ - + @@ -403,7 +403,7 @@ - + @@ -422,7 +422,7 @@ - + @@ -441,7 +441,7 @@ - + @@ -460,7 +460,7 @@ - + @@ -479,7 +479,7 @@ - + @@ -498,7 +498,7 @@ - + @@ -517,7 +517,7 @@ - + @@ -536,7 +536,7 @@ - + @@ -555,7 +555,7 @@ - + @@ -574,7 +574,7 @@ - + @@ -598,7 +598,7 @@ - + @@ -617,7 +617,7 @@ - + diff --git a/docs/test_cases/t00007_class.svg b/docs/test_cases/t00007_class.svg index ec5941e8..0f850f0f 100644 --- a/docs/test_cases/t00007_class.svg +++ b/docs/test_cases/t00007_class.svg @@ -1,6 +1,6 @@ - + @@ -9,57 +9,57 @@ - - + + A - - + + B - - + + C - - + + R - + - + a : std::unique_ptr<A> - + - + b : std::shared_ptr<B> - + - + c : std::weak_ptr<C> diff --git a/docs/test_cases/t00007_class_mermaid.svg b/docs/test_cases/t00007_class_mermaid.svg index 91383390..70acd691 100644 --- a/docs/test_cases/t00007_class_mermaid.svg +++ b/docs/test_cases/t00007_class_mermaid.svg @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + diff --git a/docs/test_cases/t00008.md b/docs/test_cases/t00008.md index 5acd5616..ada54ea5 100644 --- a/docs/test_cases/t00008.md +++ b/docs/test_cases/t00008.md @@ -346,12 +346,13 @@ template <> struct E::nested_template { "line": 29, "translation_unit": "t00008.cc" }, - "type": "B" + "type": "B" } ], "methods": [ { "access": "public", + "display_name": "add", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -379,10 +380,12 @@ template <> struct E::nested_template { "line": 33, "translation_unit": "t00008.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "D", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -404,6 +407,14 @@ template <> struct E::nested_template { "type": "std::tuple *" } ], + "template_parameters": [ + { + "is_variadic": true, + "kind": "template_type", + "name": "Items...", + "template_parameters": [] + } + ], "type": "void" } ], @@ -453,6 +464,7 @@ template <> struct E::nested_template { "methods": [ { "access": "public", + "display_name": "get", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -480,6 +492,7 @@ template <> struct E::nested_template { "line": 40, "translation_unit": "t00008.cc" }, + "template_parameters": [], "type": "DT *" } ], @@ -514,6 +527,7 @@ template <> struct E::nested_template { "methods": [ { "access": "public", + "display_name": "getDecl", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -541,6 +555,7 @@ template <> struct E::nested_template { "line": 47, "translation_unit": "t00008.cc" }, + "template_parameters": [], "type": "DeclType *" } ], diff --git a/docs/test_cases/t00008_class.svg b/docs/test_cases/t00008_class.svg index ee209a51..a113ea86 100644 --- a/docs/test_cases/t00008_class.svg +++ b/docs/test_cases/t00008_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,50 +19,50 @@ - + - + comparator : CMP - + - + ints : std::array<int,N> - + - + pointer : T * - + - + reference : T & - + - + value : T - + - + values : std::vector<P> - - + + Vector @@ -71,15 +71,15 @@ - + - + values : std::vector<T> - - + + B @@ -88,15 +88,15 @@ - + - + template_template : C<T> - - + + B @@ -105,8 +105,8 @@ - - + + D @@ -115,31 +115,31 @@ D<Items...>(std::tuple<Items...> *) : void - + - + add(int i) : void - + - + ints : B<int,Vector> - - + + E - - + + E::nested_template @@ -147,16 +147,16 @@ ET - + - + get(ET * d) : DT * - - + + E::nested_template @@ -164,11 +164,11 @@ char - + - + getDecl(char * c) : DeclType * diff --git a/docs/test_cases/t00008_class_mermaid.svg b/docs/test_cases/t00008_class_mermaid.svg index 07818610..ee05c28a 100644 --- a/docs/test_cases/t00008_class_mermaid.svg +++ b/docs/test_cases/t00008_class_mermaid.svg @@ -114,7 +114,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -187,7 +187,7 @@ - + @@ -211,7 +211,7 @@ - + @@ -230,7 +230,7 @@ - + @@ -264,7 +264,7 @@ - + @@ -283,7 +283,7 @@ - + @@ -307,7 +307,7 @@ - + diff --git a/docs/test_cases/t00009_class.svg b/docs/test_cases/t00009_class.svg index fa0862ae..abf44460 100644 --- a/docs/test_cases/t00009_class.svg +++ b/docs/test_cases/t00009_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,15 +19,15 @@ - + - + value : T - - + + A @@ -36,8 +36,8 @@ - - + + A @@ -46,8 +46,8 @@ - - + + A @@ -56,33 +56,33 @@ - - + + B - + - + aint : A<int> - + - + astring : A<std::string> * - + - + avector : A<std::vector<std::string>> & diff --git a/docs/test_cases/t00009_class_mermaid.svg b/docs/test_cases/t00009_class_mermaid.svg index 88ce66b6..67477728 100644 --- a/docs/test_cases/t00009_class_mermaid.svg +++ b/docs/test_cases/t00009_class_mermaid.svg @@ -126,7 +126,7 @@ - + @@ -150,7 +150,7 @@ - + @@ -169,7 +169,7 @@ - + @@ -188,7 +188,7 @@ - + @@ -207,7 +207,7 @@ - + diff --git a/docs/test_cases/t00010_class.svg b/docs/test_cases/t00010_class.svg index 7656e031..4fe3ecca 100644 --- a/docs/test_cases/t00010_class.svg +++ b/docs/test_cases/t00010_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,22 +19,22 @@ - + - + first : T - + - + second : P - - + + A @@ -43,8 +43,8 @@ - - + + B @@ -53,15 +53,15 @@ - + - + astring : A<T,std::string> - - + + B @@ -70,19 +70,19 @@ - - + + C - + - + aintstring : B<int> diff --git a/docs/test_cases/t00010_class_mermaid.svg b/docs/test_cases/t00010_class_mermaid.svg index a1f50bee..187318f4 100644 --- a/docs/test_cases/t00010_class_mermaid.svg +++ b/docs/test_cases/t00010_class_mermaid.svg @@ -102,7 +102,7 @@ - + @@ -131,7 +131,7 @@ - + @@ -150,7 +150,7 @@ - + @@ -174,7 +174,7 @@ - + @@ -193,7 +193,7 @@ - + diff --git a/docs/test_cases/t00011.md b/docs/test_cases/t00011.md index fee12b52..16344d60 100644 --- a/docs/test_cases/t00011.md +++ b/docs/test_cases/t00011.md @@ -113,6 +113,7 @@ public: "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -135,6 +136,7 @@ public: "line": 16, "translation_unit": "t00011.cc" }, + "template_parameters": [], "type": "void" } ], @@ -175,6 +177,7 @@ public: "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -197,6 +200,7 @@ public: "line": 28, "translation_unit": "t00011.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00011_class.svg b/docs/test_cases/t00011_class.svg index 93149cfd..4246f65f 100644 --- a/docs/test_cases/t00011_class.svg +++ b/docs/test_cases/t00011_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + D @@ -19,48 +19,48 @@ - + - + value : T - - + + A - + - + foo() : void - - + + B - + - + foo() : void - + - + m_a : A * diff --git a/docs/test_cases/t00011_class_mermaid.svg b/docs/test_cases/t00011_class_mermaid.svg index f17a0ef6..bfe72dd5 100644 --- a/docs/test_cases/t00011_class_mermaid.svg +++ b/docs/test_cases/t00011_class_mermaid.svg @@ -78,7 +78,7 @@ - + @@ -102,7 +102,7 @@ - + @@ -126,7 +126,7 @@ - + diff --git a/docs/test_cases/t00012_class.svg b/docs/test_cases/t00012_class.svg index 75cb702a..6663b0d6 100644 --- a/docs/test_cases/t00012_class.svg +++ b/docs/test_cases/t00012_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,22 +19,22 @@ - + - + value : T - + - + values : std::variant<Ts...> - - + + B @@ -43,15 +43,15 @@ - + - + ints : std::array<int,sizeof...(Is)> - - + + C @@ -60,15 +60,15 @@ - + - + ints : std::array<T,sizeof...(Is)> - - + + A @@ -77,8 +77,8 @@ - - + + A @@ -87,8 +87,8 @@ - - + + B @@ -97,8 +97,8 @@ - - + + B @@ -107,8 +107,8 @@ - - + + C @@ -117,50 +117,50 @@ - - + + R - + - + a1 : A<int,std::string,float> - + - + a2 : A<int,std::string,bool> - + - + b1 : B<3,2,1> - + - + b2 : B<1,1,1,1> - + - + c1 : C<std::map<int,std::vector<std::vector<std::vector<std::string>>>>,3,3,3> - + Long template annotation diff --git a/docs/test_cases/t00012_class_mermaid.svg b/docs/test_cases/t00012_class_mermaid.svg index 9fda8811..7ac38189 100644 --- a/docs/test_cases/t00012_class_mermaid.svg +++ b/docs/test_cases/t00012_class_mermaid.svg @@ -174,7 +174,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -227,7 +227,7 @@ - + @@ -251,7 +251,7 @@ - + @@ -270,7 +270,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -308,7 +308,7 @@ - + @@ -327,7 +327,7 @@ - + @@ -346,7 +346,7 @@ - + diff --git a/docs/test_cases/t00013.md b/docs/test_cases/t00013.md index 1e54e3d5..fed107e5 100644 --- a/docs/test_cases/t00013.md +++ b/docs/test_cases/t00013.md @@ -295,6 +295,7 @@ private: "methods": [ { "access": "public", + "display_name": "print", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -322,6 +323,7 @@ private: "line": 30, "translation_unit": "t00013.cc" }, + "template_parameters": [], "type": "void" } ], @@ -575,6 +577,7 @@ private: "methods": [ { "access": "public", + "display_name": "get_a", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -602,10 +605,12 @@ private: "line": 45, "translation_unit": "t00013.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "get_b", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -633,10 +638,12 @@ private: "line": 46, "translation_unit": "t00013.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "get_const_b", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -664,10 +671,12 @@ private: "line": 47, "translation_unit": "t00013.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "get_c", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -695,10 +704,12 @@ private: "line": 48, "translation_unit": "t00013.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "get_d", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -726,10 +737,12 @@ private: "line": 49, "translation_unit": "t00013.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "get_d2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -757,10 +770,12 @@ private: "line": 51, "translation_unit": "t00013.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "get_int_e", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -788,10 +803,12 @@ private: "line": 54, "translation_unit": "t00013.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "get_int_e2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -819,10 +836,12 @@ private: "line": 55, "translation_unit": "t00013.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "get_int_f", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -850,10 +869,12 @@ private: "line": 58, "translation_unit": "t00013.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "get_e", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -875,10 +896,19 @@ private: "type": "E" } ], + "template_parameters": [ + { + "is_variadic": false, + "kind": "template_type", + "name": "T", + "template_parameters": [] + } + ], "type": "T" }, { "access": "public", + "display_name": "get_f", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -900,6 +930,14 @@ private: "type": "const F &" } ], + "template_parameters": [ + { + "is_variadic": false, + "kind": "template_type", + "name": "T", + "template_parameters": [] + } + ], "type": "T" } ], diff --git a/docs/test_cases/t00013_class.svg b/docs/test_cases/t00013_class.svg index fe798fc7..6b59d8ff 100644 --- a/docs/test_cases/t00013_class.svg +++ b/docs/test_cases/t00013_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + ABCD::F @@ -19,15 +19,15 @@ - + - + f : T - - + + ABCD::F @@ -36,75 +36,75 @@ - - + + A - + - + a : int - - + + B - + - + b : int - - + + C - + - + c : int - - + + D - + - + print(R * r) : void - + - + d : int - - + + E @@ -113,15 +113,15 @@ - + - + e : T - - + + G @@ -130,22 +130,22 @@ - + - + args : std::tuple<Args...> - + - + g : T - - + + E @@ -154,8 +154,8 @@ - - + + G @@ -164,8 +164,8 @@ - - + + E @@ -174,93 +174,93 @@ - - + + R - + - + get_a(A * a) : int - + - + get_b(B & b) : int - + - + get_c(C c) : int - + - + get_const_b(const B & b) : int - + - + get_d(D && d) : int - + - + get_d2(D && d) : int get_e<T>(E<T> e) : T get_f<T>(const F<T> & f) : T - + - + get_int_e(const E<int> & e) : int - + - + get_int_e2(E<int> & e) : int - + - + get_int_f(const ABCD::F<int> & f) : int - + - + estring : E<std::string> - + - + gintstring : G<int,float,std::string> diff --git a/docs/test_cases/t00013_class_mermaid.svg b/docs/test_cases/t00013_class_mermaid.svg index c153220f..839757e9 100644 --- a/docs/test_cases/t00013_class_mermaid.svg +++ b/docs/test_cases/t00013_class_mermaid.svg @@ -234,7 +234,7 @@ - + @@ -258,7 +258,7 @@ - + @@ -277,7 +277,7 @@ - + @@ -301,7 +301,7 @@ - + @@ -325,7 +325,7 @@ - + @@ -349,7 +349,7 @@ - + @@ -378,7 +378,7 @@ - + @@ -402,7 +402,7 @@ - + @@ -431,7 +431,7 @@ - + @@ -450,7 +450,7 @@ - + @@ -469,7 +469,7 @@ - + @@ -488,7 +488,7 @@ - + diff --git a/docs/test_cases/t00014_class.svg b/docs/test_cases/t00014_class.svg index b64363fa..abafb6d8 100644 --- a/docs/test_cases/t00014_class.svg +++ b/docs/test_cases/t00014_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,37 +19,37 @@ - + - + p : P - + - + t : T - - + + B - + - + value : std::string - - + + A @@ -58,8 +58,8 @@ - - + + A @@ -68,8 +68,8 @@ - - + + A @@ -78,8 +78,8 @@ - - + + A @@ -88,8 +88,8 @@ - - + + A @@ -98,8 +98,8 @@ - - + + A @@ -108,8 +108,8 @@ - - + + A @@ -118,8 +118,8 @@ - - + + A @@ -128,8 +128,8 @@ - - + + A @@ -138,8 +138,8 @@ - - + + A @@ -148,8 +148,8 @@ - - + + A @@ -158,8 +158,8 @@ - - + + A @@ -168,8 +168,8 @@ - - + + A @@ -178,7 +178,7 @@ - + A @@ -186,7 +186,7 @@ char,std::string - + A @@ -194,8 +194,8 @@ wchar_t,std::string - - + + R @@ -204,116 +204,116 @@ - + - + abool : APtr<bool> - + - + aboolfloat : AAPtr<bool,float> - + - + afloat : ASharedPtr<float> - + - + atfloat : AAPtr<T,float> - + - + bapair : PairPairBA<bool> - + - + boolstring : A<bool,std::string> - + - + bs : BVector - + - + bs2 : BVector2 - + - + bstringstring : BStringString - + - + cb : SimpleCallback<ACharString> - + - + floatstring : AStringPtr<float> - + - + gcb : GenericCallback<AWCharString> - + - + intstring : AIntString - + - + stringstring : AStringString - + - + vcb : VoidCallback - + - + vps : VectorPtr<B> diff --git a/docs/test_cases/t00014_class_mermaid.svg b/docs/test_cases/t00014_class_mermaid.svg index 41abfb4e..229d38f3 100644 --- a/docs/test_cases/t00014_class_mermaid.svg +++ b/docs/test_cases/t00014_class_mermaid.svg @@ -474,7 +474,7 @@ - + @@ -503,7 +503,7 @@ - + @@ -527,7 +527,7 @@ - + @@ -546,7 +546,7 @@ - + @@ -565,7 +565,7 @@ - + @@ -584,7 +584,7 @@ - + @@ -603,7 +603,7 @@ - + @@ -622,7 +622,7 @@ - + @@ -641,7 +641,7 @@ - + @@ -660,7 +660,7 @@ - + @@ -679,7 +679,7 @@ - + @@ -698,7 +698,7 @@ - + @@ -717,7 +717,7 @@ - + @@ -736,7 +736,7 @@ - + @@ -755,7 +755,7 @@ - + @@ -774,7 +774,7 @@ - + @@ -793,7 +793,7 @@ - + @@ -812,7 +812,7 @@ - + diff --git a/docs/test_cases/t00015_class.svg b/docs/test_cases/t00015_class.svg index 2103ce95..4e66daa8 100644 --- a/docs/test_cases/t00015_class.svg +++ b/docs/test_cases/t00015_class.svg @@ -1,6 +1,6 @@ - + @@ -9,40 +9,40 @@ - - + + ns1::A - - + + ns1::ns2_v0_9_0::A - - + + ns1::Anon - - + + ns3::ns1::ns2::Anon - - + + ns3::B diff --git a/docs/test_cases/t00015_class_mermaid.svg b/docs/test_cases/t00015_class_mermaid.svg index 00baedca..fbb2e254 100644 --- a/docs/test_cases/t00015_class_mermaid.svg +++ b/docs/test_cases/t00015_class_mermaid.svg @@ -84,7 +84,7 @@ - + @@ -103,7 +103,7 @@ - + @@ -122,7 +122,7 @@ - + @@ -141,7 +141,7 @@ - + @@ -160,7 +160,7 @@ - + diff --git a/docs/test_cases/t00016_class.svg b/docs/test_cases/t00016_class.svg index 32999327..ae21d7cb 100644 --- a/docs/test_cases/t00016_class.svg +++ b/docs/test_cases/t00016_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + is_numeric @@ -21,8 +21,8 @@ value : enum - - + + is_numeric @@ -33,8 +33,8 @@ value : enum - - + + is_numeric @@ -45,8 +45,8 @@ value : enum - - + + is_numeric @@ -57,8 +57,8 @@ value : enum - - + + is_numeric @@ -69,8 +69,8 @@ value : enum - - + + is_numeric diff --git a/docs/test_cases/t00016_class_mermaid.svg b/docs/test_cases/t00016_class_mermaid.svg index 66799b77..1e8614a0 100644 --- a/docs/test_cases/t00016_class_mermaid.svg +++ b/docs/test_cases/t00016_class_mermaid.svg @@ -114,7 +114,7 @@ - + @@ -138,7 +138,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -186,7 +186,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -234,7 +234,7 @@ - + diff --git a/docs/test_cases/t00017.md b/docs/test_cases/t00017.md index ca028a62..8b71b728 100644 --- a/docs/test_cases/t00017.md +++ b/docs/test_cases/t00017.md @@ -518,6 +518,7 @@ private: "methods": [ { "access": "private", + "display_name": "R", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -561,6 +562,7 @@ private: "line": 28, "translation_unit": "t00017.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00017_class.svg b/docs/test_cases/t00017_class.svg index 531fe9ab..047b37bc 100644 --- a/docs/test_cases/t00017_class.svg +++ b/docs/test_cases/t00017_class.svg @@ -1,6 +1,6 @@ - + @@ -9,135 +9,135 @@ - - + + A - - + + B - - + + C - - + + D - - + + E - - + + F - - + + G - - + + H - - + + I - - + + J - - + + K - - + + R - + - + R(int & some_int, C & cc, const E & ee, F && ff, I *& ii) : void - + - + some_int : int - + - + some_int_pointer : int * - + - + some_int_pointer_pointer : int ** - + - + some_int_reference : int & diff --git a/docs/test_cases/t00017_class_mermaid.svg b/docs/test_cases/t00017_class_mermaid.svg index e75aef19..b27d4333 100644 --- a/docs/test_cases/t00017_class_mermaid.svg +++ b/docs/test_cases/t00017_class_mermaid.svg @@ -186,7 +186,7 @@ - + @@ -205,7 +205,7 @@ - + @@ -224,7 +224,7 @@ - + @@ -243,7 +243,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -281,7 +281,7 @@ - + @@ -300,7 +300,7 @@ - + @@ -319,7 +319,7 @@ - + @@ -338,7 +338,7 @@ - + @@ -357,7 +357,7 @@ - + @@ -376,7 +376,7 @@ - + @@ -395,7 +395,7 @@ - + diff --git a/docs/test_cases/t00018.md b/docs/test_cases/t00018.md index 3b358daa..639523e5 100644 --- a/docs/test_cases/t00018.md +++ b/docs/test_cases/t00018.md @@ -165,6 +165,7 @@ void widget::draw(const clanguml::t00018::widget &w) "methods": [ { "access": "public", + "display_name": "draw", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -192,10 +193,12 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 13, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "draw", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -223,10 +226,12 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 14, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "widget", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -254,6 +259,7 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 15, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "void" } ], @@ -294,6 +300,7 @@ void widget::draw(const clanguml::t00018::widget &w) "methods": [ { "access": "public", + "display_name": "draw", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -316,10 +323,12 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 21, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "draw", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -342,10 +351,12 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 22, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "shown", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -368,10 +379,12 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 23, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "bool" }, { "access": "public", + "display_name": "widget", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -399,10 +412,12 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 24, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "~widget", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -425,10 +440,12 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 25, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "widget", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -456,10 +473,12 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 27, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "widget", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -487,10 +506,12 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 29, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "operator=", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -518,10 +539,12 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 30, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "widget &" }, { "access": "public", + "display_name": "operator=", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -549,6 +572,7 @@ void widget::draw(const clanguml::t00018::widget &w) "line": 31, "translation_unit": "t00018.cc" }, + "template_parameters": [], "type": "widget &" } ], diff --git a/docs/test_cases/t00018_class.svg b/docs/test_cases/t00018_class.svg index c719205a..6ce5b597 100644 --- a/docs/test_cases/t00018_class.svg +++ b/docs/test_cases/t00018_class.svg @@ -1,6 +1,6 @@ - + @@ -9,121 +9,121 @@ - - + + impl::widget - + - + widget(int n) : void - + - + draw(const widget & w) const : void - + - + draw(const widget & w) : void - + - + n : int - - + + widget - + - + widget(int) : void - + - + widget(widget &&) : void - + - + widget(const widget &) = deleted : void - + - + ~widget() : void - + - + operator=(widget &&) : widget & - + - + operator=(const widget &) = deleted : widget & - + - + draw() const : void - + - + draw() : void - + - + shown() const : bool - + - + pImpl : std::unique_ptr<impl::widget> diff --git a/docs/test_cases/t00018_class_mermaid.svg b/docs/test_cases/t00018_class_mermaid.svg index 72b3aceb..16a5d357 100644 --- a/docs/test_cases/t00018_class_mermaid.svg +++ b/docs/test_cases/t00018_class_mermaid.svg @@ -78,7 +78,7 @@ - + @@ -117,7 +117,7 @@ - + diff --git a/docs/test_cases/t00019.md b/docs/test_cases/t00019.md index 88c11181..c4e9c510 100644 --- a/docs/test_cases/t00019.md +++ b/docs/test_cases/t00019.md @@ -173,6 +173,7 @@ class Base { "methods": [ { "access": "private", + "display_name": "Base", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -195,10 +196,12 @@ class Base { "line": 10, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "void" }, { "access": "private", + "display_name": "~Base", "is_const": false, "is_consteval": false, "is_constexpr": true, @@ -221,10 +224,12 @@ class Base { "line": 12, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "void" }, { "access": "private", + "display_name": "m1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -247,10 +252,12 @@ class Base { "line": 14, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "int" }, { "access": "private", + "display_name": "m2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -273,6 +280,7 @@ class Base { "line": 16, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "std::string" } ], @@ -300,6 +308,7 @@ class Base { "methods": [ { "access": "private", + "display_name": "m1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -322,10 +331,12 @@ class Base { "line": 13, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "int" }, { "access": "private", + "display_name": "m2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -348,6 +359,7 @@ class Base { "line": 19, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "std::string" } ], @@ -382,6 +394,7 @@ class Base { "methods": [ { "access": "private", + "display_name": "all_calls_count", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -404,6 +417,7 @@ class Base { "line": 14, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "int" } ], @@ -463,6 +477,7 @@ class Base { "methods": [ { "access": "private", + "display_name": "m1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -485,10 +500,12 @@ class Base { "line": 12, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "int" }, { "access": "private", + "display_name": "m2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -511,10 +528,12 @@ class Base { "line": 18, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "std::string" }, { "access": "private", + "display_name": "m1_calls", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -537,10 +556,12 @@ class Base { "line": 24, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "int" }, { "access": "private", + "display_name": "m2_calls", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -563,6 +584,7 @@ class Base { "line": 26, "translation_unit": "t00019.cc" }, + "template_parameters": [], "type": "int" } ], @@ -615,7 +637,7 @@ class Base { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00019::Base" + "type": "Base" } ], "type": "class" @@ -658,7 +680,7 @@ class Base { "type": "clanguml::t00019::Base" } ], - "type": "clanguml::t00019::Layer3" + "type": "Layer3" } ], "type": "class" @@ -708,7 +730,7 @@ class Base { "type": "clanguml::t00019::Layer3" } ], - "type": "clanguml::t00019::Layer2" + "type": "Layer2" } ], "type": "class" diff --git a/docs/test_cases/t00019_class.svg b/docs/test_cases/t00019_class.svg index 3d115d3c..5cb39c1f 100644 --- a/docs/test_cases/t00019_class.svg +++ b/docs/test_cases/t00019_class.svg @@ -1,6 +1,6 @@ - + @@ -9,45 +9,45 @@ - - + + Base - + - + Base() = default : void - + - + ~Base() constexpr = default : void - + - + m1() : int - + - + m2() : std::string - - + + Layer1 @@ -55,23 +55,23 @@ LowerLayer - + - + m1() : int - + - + m2() : std::string - - + + Layer2 @@ -79,16 +79,16 @@ LowerLayer - + - + all_calls_count() const : int - - + + Layer3 @@ -96,50 +96,50 @@ LowerLayer - + - + m1() : int - + - + m1_calls() const : int - + - + m2() : std::string - + - + m2_calls() const : int - + - + m_m1_calls : int - + - + m_m2_calls : int - + Layer3 @@ -147,7 +147,7 @@ Base - + Layer2 @@ -155,7 +155,7 @@ Layer3<Base> - + Layer1 @@ -163,19 +163,19 @@ Layer2<Layer3<Base>> - - + + A - + - + layers : std::unique_ptr<Layer1<Layer2<Layer3<Base>>>> diff --git a/docs/test_cases/t00019_class_mermaid.svg b/docs/test_cases/t00019_class_mermaid.svg index 0d6a0821..1c90ac24 100644 --- a/docs/test_cases/t00019_class_mermaid.svg +++ b/docs/test_cases/t00019_class_mermaid.svg @@ -132,7 +132,7 @@ - + @@ -171,7 +171,7 @@ - + @@ -200,7 +200,7 @@ - + @@ -224,7 +224,7 @@ - + @@ -273,7 +273,7 @@ - + @@ -292,7 +292,7 @@ - + @@ -311,7 +311,7 @@ - + @@ -330,7 +330,7 @@ - + diff --git a/docs/test_cases/t00020.md b/docs/test_cases/t00020.md index 7a3b031a..4413ea2b 100644 --- a/docs/test_cases/t00020.md +++ b/docs/test_cases/t00020.md @@ -115,6 +115,7 @@ public: "methods": [ { "access": "public", + "display_name": "~ProductA", "is_const": false, "is_consteval": false, "is_constexpr": true, @@ -137,10 +138,12 @@ public: "line": 8, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "sell", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -168,6 +171,7 @@ public: "line": 9, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "bool" } ], @@ -202,6 +206,7 @@ public: "methods": [ { "access": "public", + "display_name": "sell", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -229,6 +234,7 @@ public: "line": 14, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "bool" } ], @@ -263,6 +269,7 @@ public: "methods": [ { "access": "public", + "display_name": "sell", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -290,6 +297,7 @@ public: "line": 19, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "bool" } ], @@ -317,6 +325,7 @@ public: "methods": [ { "access": "public", + "display_name": "~ProductB", "is_const": false, "is_consteval": false, "is_constexpr": true, @@ -339,10 +348,12 @@ public: "line": 24, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "buy", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -370,6 +381,7 @@ public: "line": 25, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "bool" } ], @@ -404,6 +416,7 @@ public: "methods": [ { "access": "public", + "display_name": "buy", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -431,6 +444,7 @@ public: "line": 30, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "bool" } ], @@ -465,6 +479,7 @@ public: "methods": [ { "access": "public", + "display_name": "buy", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -492,6 +507,7 @@ public: "line": 35, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "bool" } ], @@ -519,6 +535,7 @@ public: "methods": [ { "access": "public", + "display_name": "make_a", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -541,10 +558,12 @@ public: "line": 40, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "std::unique_ptr" }, { "access": "public", + "display_name": "make_b", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -567,6 +586,7 @@ public: "line": 41, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "std::unique_ptr" } ], @@ -601,6 +621,7 @@ public: "methods": [ { "access": "public", + "display_name": "make_a", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -623,10 +644,12 @@ public: "line": 46, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "std::unique_ptr" }, { "access": "public", + "display_name": "make_b", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -649,6 +672,7 @@ public: "line": 51, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "std::unique_ptr" } ], @@ -683,6 +707,7 @@ public: "methods": [ { "access": "public", + "display_name": "make_a", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -705,10 +730,12 @@ public: "line": 59, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "std::unique_ptr" }, { "access": "public", + "display_name": "make_b", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -731,6 +758,7 @@ public: "line": 64, "translation_unit": "t00020.cc" }, + "template_parameters": [], "type": "std::unique_ptr" } ], diff --git a/docs/test_cases/t00020_class.svg b/docs/test_cases/t00020_class.svg index 9b669b9b..5510637b 100644 --- a/docs/test_cases/t00020_class.svg +++ b/docs/test_cases/t00020_class.svg @@ -1,6 +1,6 @@ - + @@ -9,175 +9,175 @@ - - + + ProductA - + - + ~ProductA() constexpr = default : void - + - + sell(int price) const = 0 : bool - - + + ProductA1 - + - + sell(int price) const : bool - - + + ProductA2 - + - + sell(int price) const : bool - - + + ProductB - + - + ~ProductB() constexpr = default : void - + - + buy(int price) const = 0 : bool - - + + ProductB1 - + - + buy(int price) const : bool - - + + ProductB2 - + - + buy(int price) const : bool - - + + AbstractFactory - + - + make_a() const = 0 : std::unique_ptr<ProductA> - + - + make_b() const = 0 : std::unique_ptr<ProductB> - - + + Factory1 - + - + make_a() const : std::unique_ptr<ProductA> - + - + make_b() const : std::unique_ptr<ProductB> - - + + Factory2 - + - + make_a() const : std::unique_ptr<ProductA> - + - + make_b() const : std::unique_ptr<ProductB> diff --git a/docs/test_cases/t00020_class_mermaid.svg b/docs/test_cases/t00020_class_mermaid.svg index 77e68d69..bfa2a740 100644 --- a/docs/test_cases/t00020_class_mermaid.svg +++ b/docs/test_cases/t00020_class_mermaid.svg @@ -186,7 +186,7 @@ - + @@ -215,7 +215,7 @@ - + @@ -239,7 +239,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -292,7 +292,7 @@ - + @@ -316,7 +316,7 @@ - + @@ -340,7 +340,7 @@ - + @@ -369,7 +369,7 @@ - + @@ -398,7 +398,7 @@ - + diff --git a/docs/test_cases/t00021.md b/docs/test_cases/t00021.md index f67c0a26..61934cfc 100644 --- a/docs/test_cases/t00021.md +++ b/docs/test_cases/t00021.md @@ -89,6 +89,7 @@ public: "methods": [ { "access": "public", + "display_name": "~Visitor", "is_const": false, "is_consteval": false, "is_constexpr": true, @@ -111,10 +112,12 @@ public: "line": 11, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "visit_A", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -142,10 +145,12 @@ public: "line": 12, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "visit_B", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -173,6 +178,7 @@ public: "line": 13, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" } ], @@ -207,6 +213,7 @@ public: "methods": [ { "access": "public", + "display_name": "visit_A", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -234,10 +241,12 @@ public: "line": 18, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "visit_B", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -265,6 +274,7 @@ public: "line": 19, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" } ], @@ -299,6 +309,7 @@ public: "methods": [ { "access": "public", + "display_name": "visit_A", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -326,10 +337,12 @@ public: "line": 24, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "visit_B", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -357,6 +370,7 @@ public: "line": 25, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" } ], @@ -391,6 +405,7 @@ public: "methods": [ { "access": "public", + "display_name": "visit_A", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -418,10 +433,12 @@ public: "line": 30, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "visit_B", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -449,6 +466,7 @@ public: "line": 31, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" } ], @@ -476,6 +494,7 @@ public: "methods": [ { "access": "public", + "display_name": "~Item", "is_const": false, "is_consteval": false, "is_constexpr": true, @@ -498,10 +517,12 @@ public: "line": 36, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "accept", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -529,6 +550,7 @@ public: "line": 37, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" } ], @@ -563,6 +585,7 @@ public: "methods": [ { "access": "public", + "display_name": "accept", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -590,6 +613,7 @@ public: "line": 42, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" } ], @@ -624,6 +648,7 @@ public: "methods": [ { "access": "public", + "display_name": "accept", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -651,6 +676,7 @@ public: "line": 47, "translation_unit": "t00021.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00021_class.svg b/docs/test_cases/t00021_class.svg index cfcc0ebf..c5647255 100644 --- a/docs/test_cases/t00021_class.svg +++ b/docs/test_cases/t00021_class.svg @@ -1,6 +1,6 @@ - + @@ -9,152 +9,152 @@ - - + + Visitor - + - + ~Visitor() constexpr = default : void - + - + visit_A(const A & item) const = 0 : void - + - + visit_B(const B & item) const = 0 : void - - + + Visitor1 - + - + visit_A(const A & item) const : void - + - + visit_B(const B & item) const : void - - + + Visitor2 - + - + visit_A(const A & item) const : void - + - + visit_B(const B & item) const : void - - + + Visitor3 - + - + visit_A(const A & item) const : void - + - + visit_B(const B & item) const : void - - + + Item - + - + ~Item() constexpr = default : void - + - + accept(const Visitor & visitor) const = 0 : void - - + + A - + - + accept(const Visitor & visitor) const : void - - + + B - + - + accept(const Visitor & visitor) const : void diff --git a/docs/test_cases/t00021_class_mermaid.svg b/docs/test_cases/t00021_class_mermaid.svg index dce81bfb..445413ea 100644 --- a/docs/test_cases/t00021_class_mermaid.svg +++ b/docs/test_cases/t00021_class_mermaid.svg @@ -236,7 +236,7 @@ - + @@ -270,7 +270,7 @@ - + @@ -299,7 +299,7 @@ - + @@ -328,7 +328,7 @@ - + @@ -357,7 +357,7 @@ - + @@ -386,7 +386,7 @@ - + @@ -410,7 +410,7 @@ - + diff --git a/docs/test_cases/t00022.md b/docs/test_cases/t00022.md index f3f741e2..1a3b41f6 100644 --- a/docs/test_cases/t00022.md +++ b/docs/test_cases/t00022.md @@ -70,6 +70,7 @@ protected: "methods": [ { "access": "public", + "display_name": "template_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -92,10 +93,12 @@ protected: "line": 8, "translation_unit": "t00022.cc" }, + "template_parameters": [], "type": "void" }, { "access": "protected", + "display_name": "method1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -118,10 +121,12 @@ protected: "line": 15, "translation_unit": "t00022.cc" }, + "template_parameters": [], "type": "void" }, { "access": "protected", + "display_name": "method2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -144,6 +149,7 @@ protected: "line": 16, "translation_unit": "t00022.cc" }, + "template_parameters": [], "type": "void" } ], @@ -178,6 +184,7 @@ protected: "methods": [ { "access": "protected", + "display_name": "method1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -200,10 +207,12 @@ protected: "line": 21, "translation_unit": "t00022.cc" }, + "template_parameters": [], "type": "void" }, { "access": "protected", + "display_name": "method2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -226,6 +235,7 @@ protected: "line": 22, "translation_unit": "t00022.cc" }, + "template_parameters": [], "type": "void" } ], @@ -260,6 +270,7 @@ protected: "methods": [ { "access": "protected", + "display_name": "method1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -282,10 +293,12 @@ protected: "line": 27, "translation_unit": "t00022.cc" }, + "template_parameters": [], "type": "void" }, { "access": "protected", + "display_name": "method2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -308,6 +321,7 @@ protected: "line": 28, "translation_unit": "t00022.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00022_class.svg b/docs/test_cases/t00022_class.svg index 072cd731..386ead15 100644 --- a/docs/test_cases/t00022_class.svg +++ b/docs/test_cases/t00022_class.svg @@ -1,6 +1,6 @@ - + @@ -9,76 +9,76 @@ - - + + A - + - + method1() = 0 : void - + - + method2() = 0 : void - + - + template_method() : void - - + + A1 - + - + method1() : void - + - + method2() : void - - + + A2 - + - + method1() : void - + - + method2() : void diff --git a/docs/test_cases/t00022_class_mermaid.svg b/docs/test_cases/t00022_class_mermaid.svg index 7182d5e7..8cb3bd8c 100644 --- a/docs/test_cases/t00022_class_mermaid.svg +++ b/docs/test_cases/t00022_class_mermaid.svg @@ -74,7 +74,7 @@ - + @@ -108,7 +108,7 @@ - + @@ -137,7 +137,7 @@ - + diff --git a/docs/test_cases/t00023.md b/docs/test_cases/t00023.md index 2ac5d7d8..ff72e480 100644 --- a/docs/test_cases/t00023.md +++ b/docs/test_cases/t00023.md @@ -79,6 +79,7 @@ private: "methods": [ { "access": "public", + "display_name": "~Strategy", "is_const": false, "is_consteval": false, "is_constexpr": true, @@ -101,10 +102,12 @@ private: "line": 8, "translation_unit": "t00023.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "algorithm", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -127,6 +130,7 @@ private: "line": 9, "translation_unit": "t00023.cc" }, + "template_parameters": [], "type": "void" } ], @@ -161,6 +165,7 @@ private: "methods": [ { "access": "public", + "display_name": "algorithm", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -183,6 +188,7 @@ private: "line": 14, "translation_unit": "t00023.cc" }, + "template_parameters": [], "type": "void" } ], @@ -217,6 +223,7 @@ private: "methods": [ { "access": "public", + "display_name": "algorithm", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -239,6 +246,7 @@ private: "line": 19, "translation_unit": "t00023.cc" }, + "template_parameters": [], "type": "void" } ], @@ -273,6 +281,7 @@ private: "methods": [ { "access": "public", + "display_name": "algorithm", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -295,6 +304,7 @@ private: "line": 24, "translation_unit": "t00023.cc" }, + "template_parameters": [], "type": "void" } ], @@ -335,6 +345,7 @@ private: "methods": [ { "access": "public", + "display_name": "Context", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -362,10 +373,12 @@ private: "line": 29, "translation_unit": "t00023.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "apply", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -388,6 +401,7 @@ private: "line": 34, "translation_unit": "t00023.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00023_class.svg b/docs/test_cases/t00023_class.svg index 3a5fe636..949aba7f 100644 --- a/docs/test_cases/t00023_class.svg +++ b/docs/test_cases/t00023_class.svg @@ -1,6 +1,6 @@ - + @@ -9,102 +9,102 @@ - - + + Strategy - + - + ~Strategy() constexpr = default : void - + - + algorithm() = 0 : void - - + + StrategyA - + - + algorithm() : void - - + + StrategyB - + - + algorithm() : void - - + + StrategyC - + - + algorithm() : void - - + + Context - + - + Context(std::unique_ptr<Strategy> strategy) : void - + - + apply() : void - + - + m_strategy : std::unique_ptr<Strategy> diff --git a/docs/test_cases/t00023_class_mermaid.svg b/docs/test_cases/t00023_class_mermaid.svg index ba5b7751..4e46a57e 100644 --- a/docs/test_cases/t00023_class_mermaid.svg +++ b/docs/test_cases/t00023_class_mermaid.svg @@ -96,7 +96,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -149,7 +149,7 @@ - + @@ -173,7 +173,7 @@ - + @@ -197,7 +197,7 @@ - + diff --git a/docs/test_cases/t00024.md b/docs/test_cases/t00024.md index e16bb8c6..7401f2a7 100644 --- a/docs/test_cases/t00024.md +++ b/docs/test_cases/t00024.md @@ -78,6 +78,7 @@ private: "methods": [ { "access": "public", + "display_name": "~Target", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -100,10 +101,12 @@ private: "line": 8, "translation_unit": "t00024.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "m1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -126,10 +129,12 @@ private: "line": 10, "translation_unit": "t00024.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "m2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -152,6 +157,7 @@ private: "line": 11, "translation_unit": "t00024.cc" }, + "template_parameters": [], "type": "void" } ], @@ -186,6 +192,7 @@ private: "methods": [ { "access": "public", + "display_name": "m1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -208,10 +215,12 @@ private: "line": 16, "translation_unit": "t00024.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "m2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -234,6 +243,7 @@ private: "line": 17, "translation_unit": "t00024.cc" }, + "template_parameters": [], "type": "void" } ], @@ -268,6 +278,7 @@ private: "methods": [ { "access": "public", + "display_name": "m1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -290,10 +301,12 @@ private: "line": 22, "translation_unit": "t00024.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "m2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -316,6 +329,7 @@ private: "line": 23, "translation_unit": "t00024.cc" }, + "template_parameters": [], "type": "void" } ], @@ -363,6 +377,7 @@ private: "methods": [ { "access": "public", + "display_name": "Proxy", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -390,10 +405,12 @@ private: "line": 28, "translation_unit": "t00024.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "m1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -416,10 +433,12 @@ private: "line": 32, "translation_unit": "t00024.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "m2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -442,6 +461,7 @@ private: "line": 33, "translation_unit": "t00024.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00024_class.svg b/docs/test_cases/t00024_class.svg index 79ad7ce8..9739f6ee 100644 --- a/docs/test_cases/t00024_class.svg +++ b/docs/test_cases/t00024_class.svg @@ -1,6 +1,6 @@ - + @@ -9,115 +9,115 @@ - - + + Target - + - + ~Target() = 0 : void - + - + m1() = 0 : void - + - + m2() = 0 : void - - + + Target1 - + - + m1() : void - + - + m2() : void - - + + Target2 - + - + m1() : void - + - + m2() : void - - + + Proxy - + - + Proxy(std::shared_ptr<Target> target) : void - + - + m1() : void - + - + m2() : void - + - + m_target : std::shared_ptr<Target> diff --git a/docs/test_cases/t00024_class_mermaid.svg b/docs/test_cases/t00024_class_mermaid.svg index 31d9e2d9..caa126e0 100644 --- a/docs/test_cases/t00024_class_mermaid.svg +++ b/docs/test_cases/t00024_class_mermaid.svg @@ -96,7 +96,7 @@ - + @@ -130,7 +130,7 @@ - + @@ -159,7 +159,7 @@ - + @@ -188,7 +188,7 @@ - + diff --git a/docs/test_cases/t00025.md b/docs/test_cases/t00025.md index 03dc44e5..b254b348 100644 --- a/docs/test_cases/t00025.md +++ b/docs/test_cases/t00025.md @@ -76,6 +76,7 @@ public: "methods": [ { "access": "public", + "display_name": "m1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -98,10 +99,12 @@ public: "line": 8, "translation_unit": "t00025.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "m2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -124,6 +127,7 @@ public: "line": 9, "translation_unit": "t00025.cc" }, + "template_parameters": [], "type": "void" } ], @@ -151,6 +155,7 @@ public: "methods": [ { "access": "public", + "display_name": "m1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -173,10 +178,12 @@ public: "line": 14, "translation_unit": "t00025.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "m2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -199,6 +206,7 @@ public: "line": 15, "translation_unit": "t00025.cc" }, + "template_parameters": [], "type": "void" } ], @@ -239,6 +247,7 @@ public: "methods": [ { "access": "public", + "display_name": "Proxy", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -266,10 +275,12 @@ public: "line": 20, "translation_unit": "t00025.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "m1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -292,10 +303,12 @@ public: "line": 24, "translation_unit": "t00025.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "m2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -318,6 +331,7 @@ public: "line": 25, "translation_unit": "t00025.cc" }, + "template_parameters": [], "type": "void" } ], @@ -363,7 +377,7 @@ public: "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00025::Target1" + "type": "Target1" } ], "type": "class" @@ -392,7 +406,7 @@ public: "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00025::Target2" + "type": "Target2" } ], "type": "class" diff --git a/docs/test_cases/t00025_class.svg b/docs/test_cases/t00025_class.svg index aed0173e..df76699f 100644 --- a/docs/test_cases/t00025_class.svg +++ b/docs/test_cases/t00025_class.svg @@ -1,6 +1,6 @@ - + @@ -9,52 +9,52 @@ - - + + Target1 - + - + m1() : void - + - + m2() : void - - + + Target2 - + - + m1() : void - + - + m2() : void - - + + Proxy @@ -62,38 +62,38 @@ T - + - + Proxy(std::shared_ptr<T> target) : void - + - + m1() : void - + - + m2() : void - + - + m_target : std::shared_ptr<T> - - + + Proxy @@ -102,8 +102,8 @@ - - + + Proxy @@ -112,26 +112,26 @@ - - + + ProxyHolder - + - + proxy1 : Proxy<Target1> - + - + proxy2 : Proxy<Target2> diff --git a/docs/test_cases/t00025_class_mermaid.svg b/docs/test_cases/t00025_class_mermaid.svg index 9891644e..2c8f0336 100644 --- a/docs/test_cases/t00025_class_mermaid.svg +++ b/docs/test_cases/t00025_class_mermaid.svg @@ -126,7 +126,7 @@ - + @@ -155,7 +155,7 @@ - + @@ -184,7 +184,7 @@ - + @@ -223,7 +223,7 @@ - + @@ -242,7 +242,7 @@ - + @@ -261,7 +261,7 @@ - + diff --git a/docs/test_cases/t00026.md b/docs/test_cases/t00026.md index e0e52803..1123fb8f 100644 --- a/docs/test_cases/t00026.md +++ b/docs/test_cases/t00026.md @@ -110,6 +110,7 @@ struct StringMemento { "methods": [ { "access": "public", + "display_name": "Memento", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -137,10 +138,12 @@ struct StringMemento { "line": 10, "translation_unit": "t00026.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "value", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -163,6 +166,7 @@ struct StringMemento { "line": 15, "translation_unit": "t00026.cc" }, + "template_parameters": [], "type": "T" } ], @@ -210,6 +214,7 @@ struct StringMemento { "methods": [ { "access": "public", + "display_name": "Originator", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -237,10 +242,12 @@ struct StringMemento { "line": 23, "translation_unit": "t00026.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "memoize_value", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -263,10 +270,12 @@ struct StringMemento { "line": 28, "translation_unit": "t00026.cc" }, + "template_parameters": [], "type": "Memento" }, { "access": "public", + "display_name": "load", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -294,10 +303,12 @@ struct StringMemento { "line": 30, "translation_unit": "t00026.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "print", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -320,10 +331,12 @@ struct StringMemento { "line": 32, "translation_unit": "t00026.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "set", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -351,6 +364,7 @@ struct StringMemento { "line": 34, "translation_unit": "t00026.cc" }, + "template_parameters": [], "type": "void" } ], @@ -398,6 +412,7 @@ struct StringMemento { "methods": [ { "access": "public", + "display_name": "state", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -425,10 +440,12 @@ struct StringMemento { "line": 42, "translation_unit": "t00026.cc" }, + "template_parameters": [], "type": "Memento &" }, { "access": "public", + "display_name": "set_state", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -460,6 +477,7 @@ struct StringMemento { "line": 44, "translation_unit": "t00026.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00026_class.svg b/docs/test_cases/t00026_class.svg index 8103e2c5..2c083dca 100644 --- a/docs/test_cases/t00026_class.svg +++ b/docs/test_cases/t00026_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + Memento @@ -18,31 +18,31 @@ T - + - + Memento(T && v) : void - + - + value() const : T - + - + m_value : T - - + + Originator @@ -50,52 +50,52 @@ T - + - + Originator(T && v) : void - + - + load(const Memento<T> & m) : void - + - + memoize_value() const : Memento<T> - + - + print() const : void - + - + set(T && v) : void - + - + m_value : T - - + + Caretaker @@ -103,30 +103,30 @@ T - + - + set_state(const std::string & s, Memento<T> && m) : void - + - + state(const std::string & n) : Memento<T> & - + - + m_mementos : std::unordered_map<std::string,Memento<T>> - - + + Caretaker @@ -135,8 +135,8 @@ - - + + Originator @@ -145,26 +145,26 @@ - - + + StringMemento - + - + caretaker : Caretaker<std::string> - + - + originator : Originator<std::string> diff --git a/docs/test_cases/t00026_class_mermaid.svg b/docs/test_cases/t00026_class_mermaid.svg index 7450ec37..b38e37ad 100644 --- a/docs/test_cases/t00026_class_mermaid.svg +++ b/docs/test_cases/t00026_class_mermaid.svg @@ -126,7 +126,7 @@ - + @@ -160,7 +160,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -243,7 +243,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -281,7 +281,7 @@ - + diff --git a/docs/test_cases/t00027.md b/docs/test_cases/t00027.md index e31c4b8a..863942b9 100644 --- a/docs/test_cases/t00027.md +++ b/docs/test_cases/t00027.md @@ -94,6 +94,7 @@ struct Window { "methods": [ { "access": "public", + "display_name": "display", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -116,10 +117,12 @@ struct Window { "line": 10, "translation_unit": "t00027.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "~Shape", "is_const": false, "is_consteval": false, "is_constexpr": true, @@ -142,6 +145,7 @@ struct Window { "line": 11, "translation_unit": "t00027.cc" }, + "template_parameters": [], "type": "void" } ], @@ -204,6 +208,7 @@ struct Window { "methods": [ { "access": "public", + "display_name": "display", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -226,6 +231,7 @@ struct Window { "line": 17, "translation_unit": "t00027.cc" }, + "template_parameters": [], "type": "void" } ], @@ -295,6 +301,7 @@ struct Window { "methods": [ { "access": "public", + "display_name": "display", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -317,6 +324,7 @@ struct Window { "line": 27, "translation_unit": "t00027.cc" }, + "template_parameters": [], "type": "void" } ], @@ -351,6 +359,7 @@ struct Window { "methods": [ { "access": "public", + "display_name": "display", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -373,6 +382,7 @@ struct Window { "line": 35, "translation_unit": "t00027.cc" }, + "template_parameters": [], "type": "void" } ], @@ -407,6 +417,7 @@ struct Window { "methods": [ { "access": "public", + "display_name": "display", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -429,6 +440,7 @@ struct Window { "line": 40, "translation_unit": "t00027.cc" }, + "template_parameters": [], "type": "void" } ], @@ -470,6 +482,7 @@ struct Window { "methods": [ { "access": "public", + "display_name": "display", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -492,6 +505,7 @@ struct Window { "line": 45, "translation_unit": "t00027.cc" }, + "template_parameters": [], "type": "void" } ], @@ -661,7 +675,7 @@ struct Window { "line": 49, "translation_unit": "t00027.cc" }, - "type": "Line" + "type": "Line" }, { "access": "public", @@ -673,7 +687,7 @@ struct Window { "line": 50, "translation_unit": "t00027.cc" }, - "type": "Line" + "type": "Line" }, { "access": "public", @@ -685,7 +699,7 @@ struct Window { "line": 51, "translation_unit": "t00027.cc" }, - "type": "Text" + "type": "Text" }, { "access": "public", @@ -697,7 +711,7 @@ struct Window { "line": 52, "translation_unit": "t00027.cc" }, - "type": "Text" + "type": "Text" } ], "methods": [], diff --git a/docs/test_cases/t00027_class.svg b/docs/test_cases/t00027_class.svg index 4a48e6f6..a969c41c 100644 --- a/docs/test_cases/t00027_class.svg +++ b/docs/test_cases/t00027_class.svg @@ -1,6 +1,6 @@ - + @@ -9,39 +9,39 @@ - - + + Shape - + - + ~Shape() constexpr = default : void - + - + display() = 0 : void - - + + Line - - + + Line @@ -49,24 +49,24 @@ T<>... - + - + display() : void - - + + Text - - + + Text @@ -74,31 +74,31 @@ T<>... - + - + display() : void - - + + ShapeDecorator - + - + display() = 0 : void - - + + Color @@ -106,16 +106,16 @@ T - + - + display() : void - - + + Weight @@ -123,16 +123,16 @@ T - + - + display() : void - - + + Line @@ -141,8 +141,8 @@ - - + + Line @@ -151,8 +151,8 @@ - - + + Text @@ -161,8 +161,8 @@ - - + + Text @@ -171,40 +171,40 @@ - - + + Window - + - + border : Line<Color,Weight> - + - + description : Text<Color> - + - + divider : Line<Color> - + - + title : Text<Color,Weight> diff --git a/docs/test_cases/t00027_class_mermaid.svg b/docs/test_cases/t00027_class_mermaid.svg index 12291553..d0b46a91 100644 --- a/docs/test_cases/t00027_class_mermaid.svg +++ b/docs/test_cases/t00027_class_mermaid.svg @@ -190,7 +190,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -238,7 +238,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -281,7 +281,7 @@ - + @@ -305,7 +305,7 @@ - + @@ -329,7 +329,7 @@ - + @@ -353,7 +353,7 @@ - + @@ -377,7 +377,7 @@ - + @@ -396,7 +396,7 @@ - + @@ -415,7 +415,7 @@ - + @@ -434,7 +434,7 @@ - + @@ -453,7 +453,7 @@ - + diff --git a/docs/test_cases/t00028.md b/docs/test_cases/t00028.md index e66b4280..19e501ab 100644 --- a/docs/test_cases/t00028.md +++ b/docs/test_cases/t00028.md @@ -416,6 +416,7 @@ class R { "methods": [ { "access": "private", + "display_name": "R", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -443,6 +444,7 @@ class R { "line": 37, "translation_unit": "t00028.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00028_class.svg b/docs/test_cases/t00028_class.svg index 3a8ba90b..e41043d4 100644 --- a/docs/test_cases/t00028_class.svg +++ b/docs/test_cases/t00028_class.svg @@ -1,6 +1,6 @@ - + @@ -9,54 +9,54 @@ - - + + A - + A class note. - - + + B - + B class note. - - + + C - + C class note. - - + + D - + D class note. - - + + E @@ -65,26 +65,26 @@ - + - + param : T - + E template class note. - - + + G - - + + F @@ -94,11 +94,11 @@ three - + F enum note. - - + + E @@ -107,70 +107,70 @@ - - + + R - + - + R(C & c) : void - + - + aaa : A - + - + bbb : B * - + - + ccc : C & - + - + ddd : std::vector<std::shared_ptr<D>> - + - + eee : E<int> - + - + ggg : G ** - + R class note. - + R contains an instance of A. - + Reference to C. diff --git a/docs/test_cases/t00028_class_mermaid.svg b/docs/test_cases/t00028_class_mermaid.svg index 10000cd0..15507814 100644 --- a/docs/test_cases/t00028_class_mermaid.svg +++ b/docs/test_cases/t00028_class_mermaid.svg @@ -218,7 +218,7 @@ - + @@ -237,7 +237,7 @@ - + @@ -256,7 +256,7 @@ - + @@ -275,7 +275,7 @@ - + @@ -294,7 +294,7 @@ - + @@ -318,7 +318,7 @@ - + @@ -337,7 +337,7 @@ - + @@ -371,7 +371,7 @@ - + @@ -390,7 +390,7 @@ - + diff --git a/docs/test_cases/t00029_class.svg b/docs/test_cases/t00029_class.svg index e980b379..d7bd07a8 100644 --- a/docs/test_cases/t00029_class.svg +++ b/docs/test_cases/t00029_class.svg @@ -1,6 +1,6 @@ - + @@ -9,16 +9,16 @@ - - + + A - - + + C @@ -27,30 +27,30 @@ - + - + param : T - - + + D - + - + param : T - - + + E @@ -60,65 +60,65 @@ three - - + + G1 - - + + G2 - - + + G3 - - + + G4 - - + + R - + - + g1 : G1 - + - + g3 : G3 & - + - + g4 : std::shared_ptr<G4> diff --git a/docs/test_cases/t00029_class_mermaid.svg b/docs/test_cases/t00029_class_mermaid.svg index e6d420bb..ebde1701 100644 --- a/docs/test_cases/t00029_class_mermaid.svg +++ b/docs/test_cases/t00029_class_mermaid.svg @@ -78,7 +78,7 @@ - + @@ -97,7 +97,7 @@ - + @@ -121,7 +121,7 @@ - + @@ -145,7 +145,7 @@ - + @@ -179,7 +179,7 @@ - + @@ -198,7 +198,7 @@ - + @@ -217,7 +217,7 @@ - + @@ -236,7 +236,7 @@ - + @@ -255,7 +255,7 @@ - + diff --git a/docs/test_cases/t00030_class.svg b/docs/test_cases/t00030_class.svg index d5591b55..2efaca3c 100644 --- a/docs/test_cases/t00030_class.svg +++ b/docs/test_cases/t00030_class.svg @@ -1,6 +1,6 @@ - + @@ -9,87 +9,87 @@ - - + + A - - + + B - - + + C - - + + D - - + + E - - + + R - + - + aaa : A - + - + bbb : std::vector<B> - + - + ccc : std::vector<C> - + - + ddd : D - + - + eee : E * diff --git a/docs/test_cases/t00030_class_mermaid.svg b/docs/test_cases/t00030_class_mermaid.svg index 8709e26f..a714fd2f 100644 --- a/docs/test_cases/t00030_class_mermaid.svg +++ b/docs/test_cases/t00030_class_mermaid.svg @@ -164,7 +164,7 @@ - + @@ -183,7 +183,7 @@ - + @@ -202,7 +202,7 @@ - + @@ -221,7 +221,7 @@ - + @@ -240,7 +240,7 @@ - + @@ -259,7 +259,7 @@ - + diff --git a/docs/test_cases/t00031.md b/docs/test_cases/t00031.md index ae7ed19d..2a2e3ea4 100644 --- a/docs/test_cases/t00031.md +++ b/docs/test_cases/t00031.md @@ -289,6 +289,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "add_b", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -316,6 +317,7 @@ struct R { "line": 28, "translation_unit": "t00031.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00031_class.svg b/docs/test_cases/t00031_class.svg index 40ccd9d8..85e23d88 100644 --- a/docs/test_cases/t00031_class.svg +++ b/docs/test_cases/t00031_class.svg @@ -1,33 +1,33 @@ - + - + - + - - - + + + A - - + + B @@ -37,8 +37,8 @@ three - - + + @@ -48,23 +48,23 @@ - + - + ttt : T - - + + D - - + + C @@ -73,47 +73,47 @@ - - + + R - + - + add_b(B b) : void - + - + aaa : A * - + - + bbb : std::vector<B> - + - + ccc : C<int> - + - + ddd : D * diff --git a/docs/test_cases/t00031_class_mermaid.svg b/docs/test_cases/t00031_class_mermaid.svg index 047d346a..12aada0c 100644 --- a/docs/test_cases/t00031_class_mermaid.svg +++ b/docs/test_cases/t00031_class_mermaid.svg @@ -126,7 +126,7 @@ - + @@ -145,7 +145,7 @@ - + @@ -179,7 +179,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -222,7 +222,7 @@ - + @@ -241,7 +241,7 @@ - + diff --git a/docs/test_cases/t00032.md b/docs/test_cases/t00032.md index e4d15f16..18d5f5e7 100644 --- a/docs/test_cases/t00032.md +++ b/docs/test_cases/t00032.md @@ -119,6 +119,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "operator()", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -141,6 +142,7 @@ struct R { "line": 12, "translation_unit": "t00032.cc" }, + "template_parameters": [], "type": "void" } ], @@ -168,6 +170,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "operator()", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -190,6 +193,7 @@ struct R { "line": 16, "translation_unit": "t00032.cc" }, + "template_parameters": [], "type": "void" } ], @@ -217,6 +221,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "operator()", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -239,6 +244,7 @@ struct R { "line": 20, "translation_unit": "t00032.cc" }, + "template_parameters": [], "type": "void" } ], @@ -363,7 +369,7 @@ struct R { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00032::TBase" + "type": "TBase" }, { "is_variadic": false, @@ -375,19 +381,19 @@ struct R { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00032::A" + "type": "A" }, { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00032::B" + "type": "B" }, { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00032::C" + "type": "C" } ], "type": "class" diff --git a/docs/test_cases/t00032_class.svg b/docs/test_cases/t00032_class.svg index 4582c9cb..47dcaef9 100644 --- a/docs/test_cases/t00032_class.svg +++ b/docs/test_cases/t00032_class.svg @@ -1,6 +1,6 @@ - + @@ -9,69 +9,69 @@ - - + + Base - - + + TBase - - + + A - + - + operator()() : void - - + + B - + - + operator()() : void - - + + C - + - + operator()() : void - - + + Overload @@ -80,15 +80,15 @@ - + - + counter : L - - + + Overload @@ -97,19 +97,19 @@ - - + + R - + - + overload : Overload<TBase,int,A,B,C> diff --git a/docs/test_cases/t00032_class_mermaid.svg b/docs/test_cases/t00032_class_mermaid.svg index ed943916..a714dd42 100644 --- a/docs/test_cases/t00032_class_mermaid.svg +++ b/docs/test_cases/t00032_class_mermaid.svg @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -166,7 +166,7 @@ - + @@ -190,7 +190,7 @@ - + @@ -214,7 +214,7 @@ - + @@ -238,7 +238,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -281,7 +281,7 @@ - + diff --git a/docs/test_cases/t00033.md b/docs/test_cases/t00033.md index 9f5a1a9d..979d39b3 100644 --- a/docs/test_cases/t00033.md +++ b/docs/test_cases/t00033.md @@ -242,7 +242,7 @@ struct R { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00033::D" + "type": "D" } ], "type": "class" @@ -335,7 +335,7 @@ struct R { "type": "std::unique_ptr" } ], - "type": "clanguml::t00033::B" + "type": "B" } ], "type": "class" diff --git a/docs/test_cases/t00033_class.svg b/docs/test_cases/t00033_class.svg index 72741b4a..9790ab60 100644 --- a/docs/test_cases/t00033_class.svg +++ b/docs/test_cases/t00033_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,15 +19,15 @@ - + - + aaa : T - - + + B @@ -36,15 +36,15 @@ - + - + bbb : T - - + + C @@ -53,30 +53,30 @@ - + - + ccc : T - - + + D - + - + ddd : int - - + + C @@ -85,8 +85,8 @@ - - + + B @@ -95,8 +95,8 @@ - - + + A @@ -105,19 +105,19 @@ - - + + R - + - + abc : A<B<std::unique_ptr<C<D>>>> diff --git a/docs/test_cases/t00033_class_mermaid.svg b/docs/test_cases/t00033_class_mermaid.svg index 1bf9ddb6..c3b9c89e 100644 --- a/docs/test_cases/t00033_class_mermaid.svg +++ b/docs/test_cases/t00033_class_mermaid.svg @@ -138,7 +138,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -186,7 +186,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -234,7 +234,7 @@ - + @@ -253,7 +253,7 @@ - + @@ -272,7 +272,7 @@ - + @@ -291,7 +291,7 @@ - + diff --git a/docs/test_cases/t00034.md b/docs/test_cases/t00034.md index 8671ef16..9aa3cd9f 100644 --- a/docs/test_cases/t00034.md +++ b/docs/test_cases/t00034.md @@ -93,6 +93,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "operator==", "is_const": true, "is_consteval": false, "is_constexpr": true, @@ -120,10 +121,12 @@ struct R { "line": 10, "translation_unit": "t00034.cc" }, + "template_parameters": [], "type": "bool" }, { "access": "public", + "display_name": "operator!=", "is_const": true, "is_consteval": false, "is_constexpr": true, @@ -151,6 +154,7 @@ struct R { "line": 11, "translation_unit": "t00034.cc" }, + "template_parameters": [], "type": "bool" } ], @@ -276,7 +280,7 @@ struct R { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00034::Void" + "type": "Void" } ], "type": "class" diff --git a/docs/test_cases/t00034_class.svg b/docs/test_cases/t00034_class.svg index a86819d1..1579e12b 100644 --- a/docs/test_cases/t00034_class.svg +++ b/docs/test_cases/t00034_class.svg @@ -1,6 +1,6 @@ - + @@ -9,30 +9,30 @@ - - + + Void - + - + operator!=(const Void &) constexpr const : bool - + - + operator==(const Void &) constexpr const : bool - - + + lift_void @@ -41,8 +41,8 @@ - - + + lift_void @@ -51,8 +51,8 @@ - - + + drop_void @@ -61,8 +61,8 @@ - - + + drop_void @@ -71,34 +71,34 @@ - - + + A - - + + R - + - + la : lift_void_t<A> * - + - + lv : lift_void_t<void> * diff --git a/docs/test_cases/t00034_class_mermaid.svg b/docs/test_cases/t00034_class_mermaid.svg index 115ec573..bb57e50f 100644 --- a/docs/test_cases/t00034_class_mermaid.svg +++ b/docs/test_cases/t00034_class_mermaid.svg @@ -102,7 +102,7 @@ - + @@ -131,7 +131,7 @@ - + @@ -150,7 +150,7 @@ - + @@ -169,7 +169,7 @@ - + @@ -188,7 +188,7 @@ - + @@ -207,7 +207,7 @@ - + @@ -226,7 +226,7 @@ - + diff --git a/docs/test_cases/t00035_class.svg b/docs/test_cases/t00035_class.svg index e7e696be..d99c35d6 100644 --- a/docs/test_cases/t00035_class.svg +++ b/docs/test_cases/t00035_class.svg @@ -1,6 +1,6 @@ - + @@ -9,40 +9,40 @@ - - + + Top - - + + Left - - + + Center - - + + Bottom - - + + Right diff --git a/docs/test_cases/t00035_class_mermaid.svg b/docs/test_cases/t00035_class_mermaid.svg index 5c19a2c3..d4b9b5a7 100644 --- a/docs/test_cases/t00035_class_mermaid.svg +++ b/docs/test_cases/t00035_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + diff --git a/docs/test_cases/t00036.md b/docs/test_cases/t00036.md index eabe606f..2b45b103 100644 --- a/docs/test_cases/t00036.md +++ b/docs/test_cases/t00036.md @@ -81,7 +81,7 @@ struct DImpl : public ns2::ns22::D { }; "blue", "yellow" ], - "display_name": "ns1::E", + "display_name": "E", "id": "2144761953049158478", "is_nested": false, "name": "E", @@ -99,7 +99,7 @@ struct DImpl : public ns2::ns22::D { }; "elements": [ { "bases": [], - "display_name": "ns1::ns11::A", + "display_name": "A", "id": "571573305652194946", "is_abstract": false, "is_nested": false, @@ -144,7 +144,7 @@ struct DImpl : public ns2::ns22::D { }; "elements": [ { "bases": [], - "display_name": "ns1::ns11::ns111::B", + "display_name": "B", "id": "1964031933563607376", "is_abstract": false, "is_nested": false, @@ -183,7 +183,7 @@ struct DImpl : public ns2::ns22::D { }; }, { "bases": [], - "display_name": "ns1::ns11::A", + "display_name": "A", "id": "1832710427462319797", "is_abstract": false, "is_nested": false, @@ -226,7 +226,7 @@ struct DImpl : public ns2::ns22::D { }; "elements": [ { "bases": [], - "display_name": "ns2::ns22::C", + "display_name": "C", "id": "2038956882066165590", "is_abstract": false, "is_nested": false, @@ -253,25 +253,6 @@ struct DImpl : public ns2::ns22::D { }; ], "name": "ns2", "type": "namespace" - }, - { - "display_name": "ns3", - "elements": [ - { - "display_name": "ns33", - "elements": [ - { - "display_name": "detail", - "name": "detail", - "type": "namespace" - } - ], - "name": "ns33", - "type": "namespace" - } - ], - "name": "ns3", - "type": "namespace" } ], "name": "t00036_class", diff --git a/docs/test_cases/t00036_class.svg b/docs/test_cases/t00036_class.svg index c1b0fd4f..b5969fcf 100644 --- a/docs/test_cases/t00036_class.svg +++ b/docs/test_cases/t00036_class.svg @@ -1,6 +1,6 @@ - + @@ -9,23 +9,23 @@ - + ns1 - + ns11 - + ns111 - + ns2 - + ns22 - - + + E @@ -34,8 +34,8 @@ yellow - - + + A @@ -44,15 +44,15 @@ - + - + a : T - - + + A @@ -61,23 +61,23 @@ - - + + B - + - + a_int : A<int> - - + + C diff --git a/docs/test_cases/t00036_class_mermaid.svg b/docs/test_cases/t00036_class_mermaid.svg index 068676d5..46fdec12 100644 --- a/docs/test_cases/t00036_class_mermaid.svg +++ b/docs/test_cases/t00036_class_mermaid.svg @@ -78,7 +78,7 @@ - + @@ -107,7 +107,7 @@ - + @@ -131,7 +131,7 @@ - + @@ -155,7 +155,7 @@ - + @@ -174,7 +174,7 @@ - + diff --git a/docs/test_cases/t00037.md b/docs/test_cases/t00037.md index f31e2e0d..0c5f56f3 100644 --- a/docs/test_cases/t00037.md +++ b/docs/test_cases/t00037.md @@ -250,6 +250,7 @@ struct A { "methods": [ { "access": "public", + "display_name": "A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -272,6 +273,7 @@ struct A { "line": 21, "translation_unit": "t00037.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00037_class.svg b/docs/test_cases/t00037_class.svg index a73acd26..67e7bb02 100644 --- a/docs/test_cases/t00037_class.svg +++ b/docs/test_cases/t00037_class.svg @@ -1,6 +1,6 @@ - + @@ -9,106 +9,106 @@ - - + + ST - + - + dimensions : ST::(anonymous_662) - + - + units : ST::(anonymous_792) - - + + ST::(dimensions) - + - + t : double - + - + x : double - + - + y : double - + - + z : double - - + + ST::(units) - + - + c : double - + - + h : double - - + + A - + - + A() : void - + - + st : ST diff --git a/docs/test_cases/t00037_class_mermaid.svg b/docs/test_cases/t00037_class_mermaid.svg index 9a14e015..d3b5982b 100644 --- a/docs/test_cases/t00037_class_mermaid.svg +++ b/docs/test_cases/t00037_class_mermaid.svg @@ -90,7 +90,7 @@ - + @@ -119,7 +119,7 @@ - + @@ -158,7 +158,7 @@ - + @@ -187,7 +187,7 @@ - + diff --git a/docs/test_cases/t00038_class.svg b/docs/test_cases/t00038_class.svg index dd937859..203e1ee6 100644 --- a/docs/test_cases/t00038_class.svg +++ b/docs/test_cases/t00038_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + thirdparty::ns1::color_t @@ -20,16 +20,16 @@ blue - - + + thirdparty::ns1::E - - + + property_t @@ -39,47 +39,47 @@ property_c - - + + A - - + + B - - + + C - - + + key_t - + - + key : std::string - - + + map @@ -88,8 +88,8 @@ - - + + map @@ -98,8 +98,8 @@ - - + + map @@ -108,8 +108,8 @@ - - + + map @@ -118,8 +118,8 @@ - - + + map diff --git a/docs/test_cases/t00038_class_mermaid.svg b/docs/test_cases/t00038_class_mermaid.svg index dab3e309..a54d1db3 100644 --- a/docs/test_cases/t00038_class_mermaid.svg +++ b/docs/test_cases/t00038_class_mermaid.svg @@ -202,7 +202,7 @@ - + @@ -236,7 +236,7 @@ - + @@ -255,7 +255,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -308,7 +308,7 @@ - + @@ -327,7 +327,7 @@ - + @@ -346,7 +346,7 @@ - + @@ -370,7 +370,7 @@ - + @@ -389,7 +389,7 @@ - + @@ -408,7 +408,7 @@ - + @@ -427,7 +427,7 @@ - + @@ -446,7 +446,7 @@ - + diff --git a/docs/test_cases/t00039.md b/docs/test_cases/t00039.md index 6b60f9e7..90b976fd 100644 --- a/docs/test_cases/t00039.md +++ b/docs/test_cases/t00039.md @@ -657,13 +657,6 @@ template struct FFF : public FF { "source": "1761969273600680013", "type": "extension" }, - { - "access": "public", - "destination": "247983380974491424", - "label": "b", - "source": "2158483243842147804", - "type": "association" - }, { "access": "public", "destination": "1761969273600680013", diff --git a/docs/test_cases/t00039_class.svg b/docs/test_cases/t00039_class.svg index 8eecc125..faafc13d 100644 --- a/docs/test_cases/t00039_class.svg +++ b/docs/test_cases/t00039_class.svg @@ -1,6 +1,6 @@ - + @@ -9,95 +9,95 @@ - - + + C - - + + D - - + + E - - + + CD - - + + DE - - + + CDE - - + + A - - + + AA - - + + AAA - + - + b : B * - - + + ns2::AAAA - - + + ns3::F @@ -106,15 +106,15 @@ - + - + t : T * - - + + ns3::FF @@ -123,15 +123,15 @@ - + - + m : M * - - + + ns3::FE @@ -140,15 +140,15 @@ - + - + m : M * - - + + ns3::FFF @@ -157,11 +157,11 @@ - + - + n : N * diff --git a/docs/test_cases/t00039_class_mermaid.svg b/docs/test_cases/t00039_class_mermaid.svg index f1deb374..52d47311 100644 --- a/docs/test_cases/t00039_class_mermaid.svg +++ b/docs/test_cases/t00039_class_mermaid.svg @@ -184,7 +184,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -222,7 +222,7 @@ - + @@ -241,7 +241,7 @@ - + @@ -260,7 +260,7 @@ - + @@ -279,7 +279,7 @@ - + @@ -298,7 +298,7 @@ - + @@ -317,7 +317,7 @@ - + @@ -336,7 +336,7 @@ - + @@ -360,7 +360,7 @@ - + @@ -379,7 +379,7 @@ - + @@ -403,7 +403,7 @@ - + @@ -427,7 +427,7 @@ - + @@ -451,7 +451,7 @@ - + diff --git a/docs/test_cases/t00040.md b/docs/test_cases/t00040.md index fe1d5978..cbd747ec 100644 --- a/docs/test_cases/t00040.md +++ b/docs/test_cases/t00040.md @@ -107,6 +107,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "get_a", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -129,6 +130,7 @@ struct R { "line": 7, "translation_unit": "t00040.cc" }, + "template_parameters": [], "type": "int" } ], @@ -217,6 +219,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "get_aaa", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -239,6 +242,7 @@ struct R { "line": 24, "translation_unit": "t00040.cc" }, + "template_parameters": [], "type": "int" } ], @@ -266,6 +270,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -293,6 +298,7 @@ struct R { "line": 32, "translation_unit": "t00040.cc" }, + "template_parameters": [], "type": "void" } ], @@ -322,12 +328,6 @@ struct R { "destination": "534115812779766127", "source": "745371908432158369", "type": "extension" - }, - { - "access": "public", - "destination": "307580006083737677", - "source": "1539035020975101539", - "type": "dependency" } ], "using_namespace": "clanguml::t00040" diff --git a/docs/test_cases/t00040_class.svg b/docs/test_cases/t00040_class.svg index d3dcf1c1..d2289705 100644 --- a/docs/test_cases/t00040_class.svg +++ b/docs/test_cases/t00040_class.svg @@ -1,6 +1,6 @@ - + @@ -9,70 +9,70 @@ - - + + A - + - + get_a() : int - + - + ii_ : int - - + + AA - - + + AAA - + - + get_aaa() : int - + - + b : B * - - + + R - + - + foo(A * a) : void diff --git a/docs/test_cases/t00040_class_mermaid.svg b/docs/test_cases/t00040_class_mermaid.svg index f6c2b035..6d7ff7ca 100644 --- a/docs/test_cases/t00040_class_mermaid.svg +++ b/docs/test_cases/t00040_class_mermaid.svg @@ -74,7 +74,7 @@ - + @@ -103,7 +103,7 @@ - + @@ -122,7 +122,7 @@ - + @@ -151,7 +151,7 @@ - + diff --git a/docs/test_cases/t00041.md b/docs/test_cases/t00041.md index d881e31d..3939dc15 100644 --- a/docs/test_cases/t00041.md +++ b/docs/test_cases/t00041.md @@ -238,6 +238,7 @@ struct NM : public N { }; "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -265,6 +266,7 @@ struct NM : public N { }; "line": 32, "translation_unit": "t00041.cc" }, + "template_parameters": [], "type": "void" } ], @@ -399,12 +401,6 @@ struct NM : public N { }; "source": "1798851434286108347", "type": "association" }, - { - "access": "public", - "destination": "648827958379389524", - "source": "175608867682236642", - "type": "dependency" - }, { "access": "public", "destination": "2158730167547707264", diff --git a/docs/test_cases/t00041_class.svg b/docs/test_cases/t00041_class.svg index f4abf989..3bc42050 100644 --- a/docs/test_cases/t00041_class.svg +++ b/docs/test_cases/t00041_class.svg @@ -1,6 +1,6 @@ - + @@ -9,107 +9,107 @@ - - + + R - - + + D - + - + rr : RR * - - + + E - - + + F - - + + RR - + - + foo(H * h) : void - + - + e : E * - + - + f : F * - + - + g : detail::G * - - + + RRR - - + + ns1::N - - + + ns1::NN - - + + ns1::NM diff --git a/docs/test_cases/t00041_class_mermaid.svg b/docs/test_cases/t00041_class_mermaid.svg index bd2d2392..e8bcc9bf 100644 --- a/docs/test_cases/t00041_class_mermaid.svg +++ b/docs/test_cases/t00041_class_mermaid.svg @@ -130,7 +130,7 @@ - + @@ -149,7 +149,7 @@ - + @@ -173,7 +173,7 @@ - + @@ -192,7 +192,7 @@ - + @@ -211,7 +211,7 @@ - + @@ -250,7 +250,7 @@ - + @@ -269,7 +269,7 @@ - + @@ -288,7 +288,7 @@ - + @@ -307,7 +307,7 @@ - + diff --git a/docs/test_cases/t00042_class.svg b/docs/test_cases/t00042_class.svg index 0bab593b..e7c23809 100644 --- a/docs/test_cases/t00042_class.svg +++ b/docs/test_cases/t00042_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,15 +19,15 @@ - + - + a : T - - + + A @@ -36,15 +36,15 @@ - + - + a : void * - - + + B @@ -53,22 +53,22 @@ - + - + b : T - + - + bb : K - - + + A @@ -77,8 +77,8 @@ - - + + A @@ -87,8 +87,8 @@ - - + + B diff --git a/docs/test_cases/t00042_class_mermaid.svg b/docs/test_cases/t00042_class_mermaid.svg index ff1bf41f..2a271c72 100644 --- a/docs/test_cases/t00042_class_mermaid.svg +++ b/docs/test_cases/t00042_class_mermaid.svg @@ -102,7 +102,7 @@ - + @@ -126,7 +126,7 @@ - + @@ -150,7 +150,7 @@ - + @@ -179,7 +179,7 @@ - + @@ -198,7 +198,7 @@ - + @@ -217,7 +217,7 @@ - + diff --git a/docs/test_cases/t00043.md b/docs/test_cases/t00043.md index be2f8518..c5474e96 100644 --- a/docs/test_cases/t00043.md +++ b/docs/test_cases/t00043.md @@ -89,7 +89,7 @@ struct J { "elements": [ { "bases": [], - "display_name": "dependants::A", + "display_name": "A", "id": "1454679300998460550", "is_abstract": false, "is_nested": false, @@ -111,7 +111,7 @@ struct J { }, { "bases": [], - "display_name": "dependants::B", + "display_name": "B", "id": "1972977265990430931", "is_abstract": false, "is_nested": false, @@ -122,6 +122,7 @@ struct J { "methods": [ { "access": "public", + "display_name": "b", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -149,6 +150,7 @@ struct J { "line": 7, "translation_unit": "t00043.cc" }, + "template_parameters": [], "type": "void" } ], @@ -165,7 +167,7 @@ struct J { }, { "bases": [], - "display_name": "dependants::BB", + "display_name": "BB", "id": "1906291555025945295", "is_abstract": false, "is_nested": false, @@ -176,6 +178,7 @@ struct J { "methods": [ { "access": "public", + "display_name": "bb", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -203,6 +206,7 @@ struct J { "line": 11, "translation_unit": "t00043.cc" }, + "template_parameters": [], "type": "void" } ], @@ -219,7 +223,7 @@ struct J { }, { "bases": [], - "display_name": "dependants::C", + "display_name": "C", "id": "823759225351121534", "is_abstract": false, "is_nested": false, @@ -230,6 +234,7 @@ struct J { "methods": [ { "access": "public", + "display_name": "c", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -257,6 +262,7 @@ struct J { "line": 15, "translation_unit": "t00043.cc" }, + "template_parameters": [], "type": "void" } ], @@ -273,7 +279,7 @@ struct J { }, { "bases": [], - "display_name": "dependants::D", + "display_name": "D", "id": "2277976215348279426", "is_abstract": false, "is_nested": false, @@ -284,6 +290,7 @@ struct J { "methods": [ { "access": "public", + "display_name": "d", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -311,10 +318,12 @@ struct J { "line": 19, "translation_unit": "t00043.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "dd", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -342,6 +351,7 @@ struct J { "line": 20, "translation_unit": "t00043.cc" }, + "template_parameters": [], "type": "void" } ], @@ -358,7 +368,7 @@ struct J { }, { "bases": [], - "display_name": "dependants::E", + "display_name": "E", "id": "1694685540293810116", "is_abstract": false, "is_nested": false, @@ -369,6 +379,7 @@ struct J { "methods": [ { "access": "public", + "display_name": "e", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -396,6 +407,7 @@ struct J { "line": 24, "translation_unit": "t00043.cc" }, + "template_parameters": [], "type": "void" } ], @@ -419,7 +431,7 @@ struct J { "elements": [ { "bases": [], - "display_name": "dependencies::G", + "display_name": "G", "id": "736400571183204899", "is_abstract": false, "is_nested": false, @@ -441,7 +453,7 @@ struct J { }, { "bases": [], - "display_name": "dependencies::GG", + "display_name": "GG", "id": "1522297681294871411", "is_abstract": false, "is_nested": false, @@ -463,7 +475,7 @@ struct J { }, { "bases": [], - "display_name": "dependencies::H", + "display_name": "H", "id": "1534191494825314170", "is_abstract": false, "is_nested": false, @@ -474,6 +486,7 @@ struct J { "methods": [ { "access": "public", + "display_name": "h", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -501,10 +514,12 @@ struct J { "line": 37, "translation_unit": "t00043.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "hh", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -532,6 +547,7 @@ struct J { "line": 38, "translation_unit": "t00043.cc" }, + "template_parameters": [], "type": "void" } ], @@ -548,7 +564,7 @@ struct J { }, { "bases": [], - "display_name": "dependencies::I", + "display_name": "I", "id": "97422543769740359", "is_abstract": false, "is_nested": false, @@ -559,6 +575,7 @@ struct J { "methods": [ { "access": "public", + "display_name": "i", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -586,6 +603,7 @@ struct J { "line": 46, "translation_unit": "t00043.cc" }, + "template_parameters": [], "type": "void" } ], @@ -602,7 +620,7 @@ struct J { }, { "bases": [], - "display_name": "dependencies::J", + "display_name": "J", "id": "1498530043106438011", "is_abstract": false, "is_nested": false, @@ -613,6 +631,7 @@ struct J { "methods": [ { "access": "public", + "display_name": "i", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -640,6 +659,7 @@ struct J { "line": 50, "translation_unit": "t00043.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00043_class.svg b/docs/test_cases/t00043_class.svg index 9499c538..af450399 100644 --- a/docs/test_cases/t00043_class.svg +++ b/docs/test_cases/t00043_class.svg @@ -1,6 +1,6 @@ - + @@ -9,167 +9,167 @@ - + dependants - + dependencies - - + + A - - + + B - + - + b(A * a) : void - - + + BB - + - + bb(A * a) : void - - + + C - + - + c(B * b) : void - - + + D - + - + d(C * c) : void - + - + dd(BB * bb) : void - - + + E - + - + e(D * d) : void - - + + G - - + + GG - - + + H - + - + h(G * g) : void - + - + hh(GG * gg) : void - - + + I - + - + i(H * h) : void - - + + J - + - + i(I * i) : void diff --git a/docs/test_cases/t00043_class_mermaid.svg b/docs/test_cases/t00043_class_mermaid.svg index 87ab9e85..33ef2ceb 100644 --- a/docs/test_cases/t00043_class_mermaid.svg +++ b/docs/test_cases/t00043_class_mermaid.svg @@ -174,7 +174,7 @@ - + @@ -193,7 +193,7 @@ - + @@ -217,7 +217,7 @@ - + @@ -241,7 +241,7 @@ - + @@ -265,7 +265,7 @@ - + @@ -294,7 +294,7 @@ - + @@ -318,7 +318,7 @@ - + @@ -337,7 +337,7 @@ - + @@ -356,7 +356,7 @@ - + @@ -385,7 +385,7 @@ - + @@ -409,7 +409,7 @@ - + diff --git a/docs/test_cases/t00044.md b/docs/test_cases/t00044.md index a4ecf101..08bb7e78 100644 --- a/docs/test_cases/t00044.md +++ b/docs/test_cases/t00044.md @@ -136,6 +136,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "sink", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -163,10 +164,12 @@ struct R { "line": 13, "translation_unit": "t00044.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "get_signal", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -183,6 +186,14 @@ struct R { "is_virtual": false, "name": "get_signal", "parameters": [], + "template_parameters": [ + { + "is_variadic": false, + "kind": "template_type", + "name": "CastTo", + "template_parameters": [] + } + ], "type": "CastTo *" } ], @@ -224,7 +235,7 @@ struct R { "template_parameters": [] } ], - "type": "clanguml::t00044::signal_handler" + "type": "signal_handler" } ], "type": "class" @@ -325,7 +336,7 @@ struct R { "type": "bool" } ], - "type": "clanguml::t00044::signal_handler" + "type": "signal_handler" } ], "type": "class" diff --git a/docs/test_cases/t00044_class.svg b/docs/test_cases/t00044_class.svg index 00f9794f..40b838ee 100644 --- a/docs/test_cases/t00044_class.svg +++ b/docs/test_cases/t00044_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + signal_handler @@ -19,8 +19,8 @@ - - + + sink @@ -28,26 +28,26 @@ signal_handler<Ret(Args...),A> - + - + sink(signal_t & sh) : void get_signal<CastTo>() : CastTo * - + - + signal : signal_t * - - + + signal_handler @@ -56,8 +56,8 @@ - - + + sink @@ -66,23 +66,23 @@ - - + + R - + - + sink1 : sink<signal_handler<void (int),bool>> - - + + signal_handler @@ -91,8 +91,8 @@ - - + + sink diff --git a/docs/test_cases/t00044_class_mermaid.svg b/docs/test_cases/t00044_class_mermaid.svg index 57c2e7f4..eee7a86b 100644 --- a/docs/test_cases/t00044_class_mermaid.svg +++ b/docs/test_cases/t00044_class_mermaid.svg @@ -138,7 +138,7 @@ - + @@ -157,7 +157,7 @@ - + @@ -191,7 +191,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -229,7 +229,7 @@ - + @@ -253,7 +253,7 @@ - + @@ -272,7 +272,7 @@ - + diff --git a/docs/test_cases/t00045.md b/docs/test_cases/t00045.md index 4659275c..dad35251 100644 --- a/docs/test_cases/t00045.md +++ b/docs/test_cases/t00045.md @@ -419,6 +419,7 @@ public: "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -446,6 +447,7 @@ public: "line": 40, "translation_unit": "t00045.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00045_class.svg b/docs/test_cases/t00045_class.svg index ddbba523..e606bd6a 100644 --- a/docs/test_cases/t00045_class.svg +++ b/docs/test_cases/t00045_class.svg @@ -1,6 +1,6 @@ - + @@ -9,32 +9,32 @@ - - + + A - - + + AA - - + + AAA - - + + AAAA @@ -43,110 +43,110 @@ - + - + t : T - - + + ns1::A - - + + ns1::ns2::A - - + + ns1::ns2::B - - + + ns1::ns2::C - - + + ns1::ns2::D - - + + ns1::ns2::E - - + + ns1::ns2::AAA - - + + ns1::ns2::R - + - + foo(AA & aa) : void - + - + a : A * - + - + ns1_a : ns1::A * - + - + ns1_ns2_a : ns1::ns2::A * - + - + root_a : ::A * diff --git a/docs/test_cases/t00045_class_mermaid.svg b/docs/test_cases/t00045_class_mermaid.svg index a8f03121..a5c9d72a 100644 --- a/docs/test_cases/t00045_class_mermaid.svg +++ b/docs/test_cases/t00045_class_mermaid.svg @@ -166,7 +166,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -223,7 +223,7 @@ - + @@ -247,7 +247,7 @@ - + @@ -266,7 +266,7 @@ - + @@ -285,7 +285,7 @@ - + @@ -304,7 +304,7 @@ - + @@ -323,7 +323,7 @@ - + @@ -342,7 +342,7 @@ - + @@ -361,7 +361,7 @@ - + @@ -380,7 +380,7 @@ - + diff --git a/docs/test_cases/t00046.md b/docs/test_cases/t00046.md index 46bccef1..afd585dd 100644 --- a/docs/test_cases/t00046.md +++ b/docs/test_cases/t00046.md @@ -109,7 +109,7 @@ public: "elements": [ { "bases": [], - "display_name": "ns1::A", + "display_name": "A", "id": "619642232943663499", "is_abstract": false, "is_nested": false, @@ -134,7 +134,7 @@ public: "elements": [ { "bases": [], - "display_name": "ns1::ns2::A", + "display_name": "A", "id": "2207007194029669343", "is_abstract": false, "is_nested": false, @@ -163,7 +163,7 @@ public: "name": "ns1::ns2::A" } ], - "display_name": "ns1::ns2::B", + "display_name": "B", "id": "204051985124373077", "is_abstract": false, "is_nested": false, @@ -192,7 +192,7 @@ public: "name": "ns1::A" } ], - "display_name": "ns1::ns2::C", + "display_name": "C", "id": "1837009554564742531", "is_abstract": false, "is_nested": false, @@ -221,7 +221,7 @@ public: "name": "ns1::ns2::A" } ], - "display_name": "ns1::ns2::D", + "display_name": "D", "id": "2029929560931799980", "is_abstract": false, "is_nested": false, @@ -250,7 +250,7 @@ public: "name": "A" } ], - "display_name": "ns1::ns2::E", + "display_name": "E", "id": "2305358535757579772", "is_abstract": false, "is_nested": false, @@ -272,7 +272,7 @@ public: }, { "bases": [], - "display_name": "ns1::ns2::R", + "display_name": "R", "id": "974430595320588991", "is_abstract": false, "is_nested": false, @@ -344,6 +344,7 @@ public: "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -371,6 +372,7 @@ public: "line": 32, "translation_unit": "t00046.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00046_class.svg b/docs/test_cases/t00046_class.svg index d329cd89..e0bbe1c7 100644 --- a/docs/test_cases/t00046_class.svg +++ b/docs/test_cases/t00046_class.svg @@ -1,6 +1,6 @@ - + @@ -9,120 +9,120 @@ - + ns1 - + ns2 - - + + A - - + + A - - + + B - - + + C - - + + D - - + + E - - + + R - + - + foo(AA & aa) : void - + - + a : A * - + - + i : std::vector<std::uint8_t> - + - + ns1_a : ns1::A * - + - + ns1_ns2_a : ns1::ns2::A * - + - + root_a : ::A * - - + + A - - + + AA diff --git a/docs/test_cases/t00046_class_mermaid.svg b/docs/test_cases/t00046_class_mermaid.svg index 812c9a6a..ada25902 100644 --- a/docs/test_cases/t00046_class_mermaid.svg +++ b/docs/test_cases/t00046_class_mermaid.svg @@ -154,7 +154,7 @@ - + @@ -173,7 +173,7 @@ - + @@ -192,7 +192,7 @@ - + @@ -211,7 +211,7 @@ - + @@ -230,7 +230,7 @@ - + @@ -249,7 +249,7 @@ - + @@ -268,7 +268,7 @@ - + @@ -287,7 +287,7 @@ - + @@ -306,7 +306,7 @@ - + diff --git a/docs/test_cases/t00047_class.svg b/docs/test_cases/t00047_class.svg index 0a473ae6..bb834e8b 100644 --- a/docs/test_cases/t00047_class.svg +++ b/docs/test_cases/t00047_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + conditional_t @@ -19,8 +19,8 @@ - - + + conditional_t @@ -29,8 +29,8 @@ - - + + conditional_t @@ -39,8 +39,8 @@ - - + + conditional_t diff --git a/docs/test_cases/t00047_class_mermaid.svg b/docs/test_cases/t00047_class_mermaid.svg index df6d1eee..01ad11cf 100644 --- a/docs/test_cases/t00047_class_mermaid.svg +++ b/docs/test_cases/t00047_class_mermaid.svg @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + diff --git a/docs/test_cases/t00048.md b/docs/test_cases/t00048.md index 53abd167..dda45eb2 100644 --- a/docs/test_cases/t00048.md +++ b/docs/test_cases/t00048.md @@ -152,6 +152,7 @@ template struct BaseTemplate { "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -174,6 +175,7 @@ template struct BaseTemplate { "line": 9, "translation_unit": "b_t00048.cc" }, + "template_parameters": [], "type": "void" } ], @@ -214,6 +216,7 @@ template struct BaseTemplate { "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -236,6 +239,7 @@ template struct BaseTemplate { "line": 15, "translation_unit": "b_t00048.cc" }, + "template_parameters": [], "type": "void" } ], @@ -290,6 +294,7 @@ template struct BaseTemplate { "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -312,6 +317,7 @@ template struct BaseTemplate { "line": 11, "translation_unit": "b_t00048.cc" }, + "template_parameters": [], "type": "void" } ], @@ -359,6 +365,7 @@ template struct BaseTemplate { "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -381,6 +388,7 @@ template struct BaseTemplate { "line": 17, "translation_unit": "b_t00048.cc" }, + "template_parameters": [], "type": "void" } ], @@ -435,6 +443,7 @@ template struct BaseTemplate { "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -457,6 +466,7 @@ template struct BaseTemplate { "line": 11, "translation_unit": "a_t00048.cc" }, + "template_parameters": [], "type": "void" } ], @@ -504,6 +514,7 @@ template struct BaseTemplate { "methods": [ { "access": "public", + "display_name": "foo", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -526,6 +537,7 @@ template struct BaseTemplate { "line": 17, "translation_unit": "a_t00048.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00048_class.svg b/docs/test_cases/t00048_class.svg index d334e58a..74a92b6b 100644 --- a/docs/test_cases/t00048_class.svg +++ b/docs/test_cases/t00048_class.svg @@ -1,6 +1,6 @@ - + @@ -9,30 +9,30 @@ - - + + Base - + - + foo() = 0 : void - + - + base : int - - + + BaseTemplate @@ -40,45 +40,45 @@ T - + - + foo() = 0 : void - + - + base : T - - + + B - + - + foo() : void - + - + b : int - - + + BTemplate @@ -86,45 +86,45 @@ T - + - + foo() : void - + - + b : T - - + + A - + - + foo() : void - + - + a : int - - + + ATemplate @@ -132,19 +132,19 @@ T - + - + foo() : void - + - + a : T diff --git a/docs/test_cases/t00048_class_mermaid.svg b/docs/test_cases/t00048_class_mermaid.svg index 381c7a8e..7df3c1f1 100644 --- a/docs/test_cases/t00048_class_mermaid.svg +++ b/docs/test_cases/t00048_class_mermaid.svg @@ -94,7 +94,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -152,7 +152,7 @@ - + @@ -181,7 +181,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -239,7 +239,7 @@ - + diff --git a/docs/test_cases/t00049.md b/docs/test_cases/t00049.md index e076aaab..39fd3a6c 100644 --- a/docs/test_cases/t00049.md +++ b/docs/test_cases/t00049.md @@ -79,6 +79,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "get_a", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -101,6 +102,7 @@ struct R { "line": 10, "translation_unit": "t00049.cc" }, + "template_parameters": [], "type": "T &" } ], @@ -229,7 +231,7 @@ struct R { "line": 14, "translation_unit": "t00049.cc" }, - "type": "A>" + "type": "A" }, { "access": "public", @@ -241,7 +243,7 @@ struct R { "line": 15, "translation_unit": "t00049.cc" }, - "type": "A>" + "type": "A" }, { "access": "public", @@ -253,12 +255,13 @@ struct R { "line": 16, "translation_unit": "t00049.cc" }, - "type": "A>" + "type": "A" } ], "methods": [ { "access": "public", + "display_name": "get_int_map", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -281,10 +284,12 @@ struct R { "line": 18, "translation_unit": "t00049.cc" }, - "type": "clanguml::t00049::A>" + "template_parameters": [], + "type": "clanguml::t00049::A" }, { "access": "public", + "display_name": "set_int_map", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -312,6 +317,7 @@ struct R { "line": 20, "translation_unit": "t00049.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00049_class.svg b/docs/test_cases/t00049_class.svg index 73cf427c..3c2ea898 100644 --- a/docs/test_cases/t00049_class.svg +++ b/docs/test_cases/t00049_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -18,23 +18,23 @@ T - + - + get_a() : T & - + - + a : T - - + + A @@ -43,8 +43,8 @@ - - + + A @@ -53,8 +53,8 @@ - - + + A @@ -63,47 +63,47 @@ - - + + R - + - + get_int_map() : A<intmap> - + - + set_int_map(A<intmap> && int_map) : void - + - + a_int_map : A<intmap> - + - + a_string : A<thestring> - + - + a_vector_string : A<string_vector> diff --git a/docs/test_cases/t00049_class_mermaid.svg b/docs/test_cases/t00049_class_mermaid.svg index 7d27ebf4..bca14350 100644 --- a/docs/test_cases/t00049_class_mermaid.svg +++ b/docs/test_cases/t00049_class_mermaid.svg @@ -126,7 +126,7 @@ - + @@ -155,7 +155,7 @@ - + @@ -174,7 +174,7 @@ - + @@ -193,7 +193,7 @@ - + @@ -212,7 +212,7 @@ - + diff --git a/docs/test_cases/t00050_class.svg b/docs/test_cases/t00050_class.svg index cf46947d..7c318334 100644 --- a/docs/test_cases/t00050_class.svg +++ b/docs/test_cases/t00050_class.svg @@ -1,6 +1,6 @@ - + @@ -9,40 +9,40 @@ - - + + A - - + + B - - + + C - - + + utils::D - - + + E @@ -52,8 +52,8 @@ E3 - - + + F @@ -62,43 +62,43 @@ - + - + t : T[N] - + - + v : V - - + + G - - + + NoComment - + Lorem ipsum dolor sit - + Lorem ipsum dolor sit - + Lorem ipsum dolor sit amet consectetur adipiscing elit, urna consequat felis vehicula class ultricies mollis dictumst, aenean non a in donec nulla. @@ -125,50 +125,50 @@ imperdiet praesent magnis ridiculus congue gravida curabitur dictum sagittis, enim et magna sit inceptos sodales parturient pharetra mollis, aenean vel nostra tellus commodo pretium sapien sociosqu. - + This is a short description of class G. - + This is an intermediate description of class G. - + This is a long description of class G. - + Lorem ipsum - + TODO 1. Write meaningful comment - + TODO 2. Write tests - + TODO 3. Implement - + Long comment example - + TODO Implement... - + Simple array wrapper. - + Template parameters diff --git a/docs/test_cases/t00050_class_mermaid.svg b/docs/test_cases/t00050_class_mermaid.svg index 7e726b4f..80a97e83 100644 --- a/docs/test_cases/t00050_class_mermaid.svg +++ b/docs/test_cases/t00050_class_mermaid.svg @@ -184,7 +184,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -222,7 +222,7 @@ - + @@ -241,7 +241,7 @@ - + @@ -260,7 +260,7 @@ - + @@ -294,7 +294,7 @@ - + @@ -323,7 +323,7 @@ - + @@ -342,7 +342,7 @@ - + diff --git a/docs/test_cases/t00051.md b/docs/test_cases/t00051.md index 1f8cfe80..517e4ad2 100644 --- a/docs/test_cases/t00051.md +++ b/docs/test_cases/t00051.md @@ -133,6 +133,7 @@ A::custom_thread2 A::start_thread2() "methods": [ { "access": "public", + "display_name": "B", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -164,10 +165,12 @@ A::custom_thread2 A::start_thread2() "line": 7, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "f", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -190,10 +193,12 @@ A::custom_thread2 A::start_thread2() "line": 13, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "ff", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -216,6 +221,7 @@ A::custom_thread2 A::start_thread2() "line": 14, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "void" } ], @@ -289,6 +295,7 @@ A::custom_thread2 A::start_thread2() "methods": [ { "access": "public", + "display_name": "B", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -320,10 +327,12 @@ A::custom_thread2 A::start_thread2() "line": 7, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "f", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -346,10 +355,12 @@ A::custom_thread2 A::start_thread2() "line": 13, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "ff", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -372,6 +383,7 @@ A::custom_thread2 A::start_thread2() "line": 14, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "void" } ], @@ -412,6 +424,7 @@ A::custom_thread2 A::start_thread2() "methods": [ { "access": "private", + "display_name": "start_thread1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -434,10 +447,12 @@ A::custom_thread2 A::start_thread2() "line": 33, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "custom_thread1" }, { "access": "private", + "display_name": "start_thread2", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -460,10 +475,12 @@ A::custom_thread2 A::start_thread2() "line": 39, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "custom_thread2" }, { "access": "private", + "display_name": "start_thread3", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -486,10 +503,12 @@ A::custom_thread2 A::start_thread2() "line": 41, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "clanguml::t00051::B<(lambda at t00051.cc:43:18),(lambda at t00051.cc:43:27)>" }, { "access": "private", + "display_name": "get_function", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -512,6 +531,7 @@ A::custom_thread2 A::start_thread2() "line": 46, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "(lambda at t00051.cc:48:16)" } ], @@ -546,6 +566,7 @@ A::custom_thread2 A::start_thread2() "methods": [ { "access": "public", + "display_name": "custom_thread1", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -571,6 +592,20 @@ A::custom_thread2 A::start_thread2() "type": "Args &&..." } ], + "template_parameters": [ + { + "is_variadic": false, + "kind": "template_type", + "name": "Function", + "template_parameters": [] + }, + { + "is_variadic": true, + "kind": "template_type", + "name": "Args...", + "template_parameters": [] + } + ], "type": "void" } ], @@ -605,6 +640,7 @@ A::custom_thread2 A::start_thread2() "methods": [ { "access": "public", + "display_name": "thread", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -632,6 +668,7 @@ A::custom_thread2 A::start_thread2() "line": 36, "translation_unit": "t00051.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00051_class.svg b/docs/test_cases/t00051_class.svg index da7b5aa1..847486ea 100644 --- a/docs/test_cases/t00051_class.svg +++ b/docs/test_cases/t00051_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + B @@ -18,45 +18,45 @@ F,FF=F - + - + B(F && f, FF && ff) : void - + - + f() : void - + - + ff() : void - + - + f_ : F - + - + ff_ : FF - - + + B @@ -64,81 +64,81 @@ (lambda at t00051.cc:43:18),(lambda at t00051.cc:43:27) - + - + B((lambda at t00051.cc:43:18) && f, (lambda at t00051.cc:43:27) && ff) : void - + - + f() : void - + - + ff() : void - + - + f_ : (lambda at t00051.cc:43:18) - + - + ff_ : (lambda at t00051.cc:43:27) - - + + A - + - + get_function() : (lambda at t00051.cc:48:16) - + - + start_thread1() : custom_thread1 - + - + start_thread2() : custom_thread2 - + - + start_thread3() : B<(lambda at t00051.cc:43:18),(lambda at t00051.cc:43:27)> - - + + A::custom_thread1 @@ -147,18 +147,18 @@ custom_thread1<Function,Args...>(Function && f, Args &&... args) : void - - + + A::custom_thread2 - + - + thread((lambda at t00051.cc:59:27) &&) : void diff --git a/docs/test_cases/t00051_class_mermaid.svg b/docs/test_cases/t00051_class_mermaid.svg index d534a2ac..c6a978e3 100644 --- a/docs/test_cases/t00051_class_mermaid.svg +++ b/docs/test_cases/t00051_class_mermaid.svg @@ -102,7 +102,7 @@ - + @@ -146,7 +146,7 @@ - + @@ -190,7 +190,7 @@ - + @@ -229,7 +229,7 @@ - + @@ -253,7 +253,7 @@ - + diff --git a/docs/test_cases/t00052.md b/docs/test_cases/t00052.md index 8e841b26..9531cbd7 100644 --- a/docs/test_cases/t00052.md +++ b/docs/test_cases/t00052.md @@ -72,6 +72,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "a", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -93,10 +94,19 @@ struct R { "type": "T" } ], + "template_parameters": [ + { + "is_variadic": false, + "kind": "template_type", + "name": "T", + "template_parameters": [] + } + ], "type": "T" }, { "access": "public", + "display_name": "aa", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -122,6 +132,20 @@ struct R { "type": "Q" } ], + "template_parameters": [ + { + "is_variadic": false, + "kind": "template_type", + "name": "F", + "template_parameters": [] + }, + { + "is_variadic": false, + "kind": "template_type", + "name": "Q", + "template_parameters": [] + } + ], "type": "void" } ], @@ -149,6 +173,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "b", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -176,10 +201,12 @@ struct R { "line": 15, "translation_unit": "t00052.cc" }, + "template_parameters": [], "type": "T" }, { "access": "public", + "display_name": "bb", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -205,6 +232,14 @@ struct R { "type": "T" } ], + "template_parameters": [ + { + "is_variadic": false, + "kind": "template_type", + "name": "F", + "template_parameters": [] + } + ], "type": "T" } ], @@ -239,6 +274,7 @@ struct R { "methods": [ { "access": "private", + "display_name": "c

", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -260,6 +296,14 @@ struct R { "type": "P" } ], + "template_parameters": [ + { + "is_variadic": false, + "kind": "template_type", + "name": "P", + "template_parameters": [] + } + ], "type": "T" } ], diff --git a/docs/test_cases/t00052_class.svg b/docs/test_cases/t00052_class.svg index fb9677a7..9691db45 100644 --- a/docs/test_cases/t00052_class.svg +++ b/docs/test_cases/t00052_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -21,8 +21,8 @@ aa<F,Q>(F && f, Q q) : void - - + + B @@ -30,18 +30,18 @@ T - + - + b(T t) : T bb<F>(F && f, T t) : T - - + + C @@ -52,8 +52,8 @@ c<P>(P p) : T - - + + B @@ -62,8 +62,8 @@ - - + + C @@ -72,33 +72,33 @@ - - + + R - + - + a : A - + - + b : B<int> - + - + c : C<int> diff --git a/docs/test_cases/t00052_class_mermaid.svg b/docs/test_cases/t00052_class_mermaid.svg index a64eb1e5..8e80188d 100644 --- a/docs/test_cases/t00052_class_mermaid.svg +++ b/docs/test_cases/t00052_class_mermaid.svg @@ -114,7 +114,7 @@ - + @@ -143,7 +143,7 @@ - + @@ -172,7 +172,7 @@ - + @@ -196,7 +196,7 @@ - + @@ -215,7 +215,7 @@ - + @@ -234,7 +234,7 @@ - + diff --git a/docs/test_cases/t00053_class.svg b/docs/test_cases/t00053_class.svg index e6cf7309..8dd900c2 100644 --- a/docs/test_cases/t00053_class.svg +++ b/docs/test_cases/t00053_class.svg @@ -1,6 +1,6 @@ - + @@ -9,72 +9,72 @@ - - + + A - - + + C - - + + E - - + + F - - + + a - - + + c - - + + e - - + + f - - + + h @@ -82,8 +82,8 @@ hhh - - + + j @@ -91,56 +91,56 @@ jjj - - + + b - - + + d - - + + g - - + + B - - + + D - - + + G - - + + i diff --git a/docs/test_cases/t00053_class_mermaid.svg b/docs/test_cases/t00053_class_mermaid.svg index c53c09cd..250b7f96 100644 --- a/docs/test_cases/t00053_class_mermaid.svg +++ b/docs/test_cases/t00053_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -166,7 +166,7 @@ - + @@ -190,7 +190,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -228,7 +228,7 @@ - + @@ -247,7 +247,7 @@ - + @@ -266,7 +266,7 @@ - + @@ -285,7 +285,7 @@ - + @@ -304,7 +304,7 @@ - + @@ -323,7 +323,7 @@ - + @@ -342,7 +342,7 @@ - + @@ -366,7 +366,7 @@ - + diff --git a/docs/test_cases/t00054.md b/docs/test_cases/t00054.md index 735a6e90..c4ed53bf 100644 --- a/docs/test_cases/t00054.md +++ b/docs/test_cases/t00054.md @@ -119,7 +119,7 @@ enum class j { jjj }; "elements": [ { "bases": [], - "display_name": "detail::c", + "display_name": "c", "id": "1168031834662719964", "is_abstract": false, "is_nested": false, @@ -141,7 +141,7 @@ enum class j { jjj }; }, { "bases": [], - "display_name": "detail::d", + "display_name": "d", "id": "1569559620782547158", "is_abstract": false, "is_nested": false, @@ -163,7 +163,7 @@ enum class j { jjj }; }, { "bases": [], - "display_name": "detail::e", + "display_name": "e", "id": "2037550833462858827", "is_abstract": false, "is_nested": false, @@ -280,7 +280,7 @@ enum class j { jjj }; "elements": [ { "bases": [], - "display_name": "detail2::C", + "display_name": "C", "id": "540054955081677892", "is_abstract": false, "is_nested": false, @@ -305,7 +305,7 @@ enum class j { jjj }; "elements": [ { "bases": [], - "display_name": "detail2::detail3::D", + "display_name": "D", "id": "1266390196945323478", "is_abstract": false, "is_nested": false, @@ -327,7 +327,7 @@ enum class j { jjj }; }, { "bases": [], - "display_name": "detail2::detail3::E", + "display_name": "E", "id": "134928214982255105", "is_abstract": false, "is_nested": false, @@ -353,7 +353,7 @@ enum class j { jjj }; }, { "bases": [], - "display_name": "detail2::F", + "display_name": "F", "id": "446694692150903211", "is_abstract": false, "is_nested": false, @@ -406,7 +406,7 @@ enum class j { jjj }; "constants": [ "hhh" ], - "display_name": "detail4::h", + "display_name": "h", "id": "1592677999268391183", "is_nested": false, "name": "h", @@ -423,7 +423,7 @@ enum class j { jjj }; "constants": [ "iii" ], - "display_name": "detail4::i", + "display_name": "i", "id": "441521323390223397", "is_nested": false, "name": "i", @@ -440,7 +440,7 @@ enum class j { jjj }; "constants": [ "jjj" ], - "display_name": "detail4::j", + "display_name": "j", "id": "499334434426587347", "is_nested": false, "name": "j", diff --git a/docs/test_cases/t00054_class.svg b/docs/test_cases/t00054_class.svg index 4b138025..c95fff0c 100644 --- a/docs/test_cases/t00054_class.svg +++ b/docs/test_cases/t00054_class.svg @@ -1,6 +1,6 @@ - + @@ -9,28 +9,28 @@ - + detail - + detail2 - + detail3 - + detail4 - - + + d - - + + a @@ -40,8 +40,8 @@ - - + + c @@ -51,8 +51,8 @@ - - + + e @@ -62,40 +62,40 @@ - - + + C - - + + F - - + + D - - + + E - - + + A @@ -104,8 +104,8 @@ - - + + B @@ -114,8 +114,8 @@ - - + + f @@ -124,8 +124,8 @@ - - + + G @@ -133,8 +133,8 @@ - - + + h @@ -143,8 +143,8 @@ hhh - - + + i @@ -153,8 +153,8 @@ iii - - + + j @@ -163,16 +163,16 @@ jjj - - + + b - - + + g diff --git a/docs/test_cases/t00054_class_mermaid.svg b/docs/test_cases/t00054_class_mermaid.svg index 51431ed8..f7a33fd2 100644 --- a/docs/test_cases/t00054_class_mermaid.svg +++ b/docs/test_cases/t00054_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -166,7 +166,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -223,7 +223,7 @@ - + @@ -242,7 +242,7 @@ - + @@ -261,7 +261,7 @@ - + @@ -280,7 +280,7 @@ - + @@ -304,7 +304,7 @@ - + @@ -328,7 +328,7 @@ - + @@ -352,7 +352,7 @@ - + @@ -371,7 +371,7 @@ - + diff --git a/docs/test_cases/t00055_class.svg b/docs/test_cases/t00055_class.svg index 353472dd..294ccbfa 100644 --- a/docs/test_cases/t00055_class.svg +++ b/docs/test_cases/t00055_class.svg @@ -1,6 +1,6 @@ - + @@ -9,80 +9,80 @@ - - + + A - - + + B - - + + C - - + + D - - + + E - - + + F - - + + G - - + + H - - + + I - - + + J diff --git a/docs/test_cases/t00055_class_mermaid.svg b/docs/test_cases/t00055_class_mermaid.svg index 1a1c1ffd..beedb800 100644 --- a/docs/test_cases/t00055_class_mermaid.svg +++ b/docs/test_cases/t00055_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -166,7 +166,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -223,7 +223,7 @@ - + diff --git a/docs/test_cases/t00056_class.svg b/docs/test_cases/t00056_class.svg index 0c6695a1..68f3d7d2 100644 --- a/docs/test_cases/t00056_class.svg +++ b/docs/test_cases/t00056_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + «concept» @@ -20,8 +20,8 @@ - - + + «concept» @@ -33,8 +33,8 @@ sizeof (l) > sizeof (r) - - + + «concept» @@ -44,8 +44,8 @@ - - + + «concept» @@ -58,8 +58,8 @@ container.begin() container.end() - - + + «concept» @@ -71,8 +71,8 @@ typename T::value_type - - + + «concept» @@ -86,8 +86,8 @@ {std::to_string(s)} noexcept {std::to_string(s)} -> std::same_as<std::string> - - + + «concept» @@ -97,8 +97,8 @@ - - + + «concept» @@ -108,8 +108,8 @@ - - + + A @@ -118,15 +118,15 @@ - + - + a : T - - + + B @@ -135,15 +135,15 @@ - + - + b : T - - + + C @@ -152,15 +152,15 @@ - + - + c : T - - + + D @@ -169,8 +169,8 @@ - - + + E @@ -179,29 +179,29 @@ - + - + e1 : T1 - + - + e2 : T2 - + - + e3 : T3 - - + + F @@ -210,25 +210,25 @@ - + - + f1 : T1 - + - + f2 : T2 - + - + f3 : T3 diff --git a/docs/test_cases/t00056_class_mermaid.svg b/docs/test_cases/t00056_class_mermaid.svg index 0096bfdd..71004f59 100644 --- a/docs/test_cases/t00056_class_mermaid.svg +++ b/docs/test_cases/t00056_class_mermaid.svg @@ -1,4 +1,4 @@ - + @@ -50,23 +50,23 @@ - - - + + + - - + + - + - - - + + + - +
@@ -88,7 +88,7 @@ - +
@@ -143,7 +143,7 @@ - +
@@ -165,7 +165,7 @@ - +
@@ -222,7 +222,7 @@ - + @@ -241,11 +241,11 @@ - + - +
@@ -257,20 +257,20 @@ greater_than_with_requires<T,P>
- -
- "sizeof (l) > sizeof (r)" -
-
- +
"(T l,P r)"
+ +
+ "sizeof(l) : > sizeof (r)" +
+
- + @@ -289,11 +289,11 @@ - + - - - + + +
@@ -305,25 +305,25 @@ iterable<T>
- -
- "container.begin()" -
-
- -
- "container.end()" -
-
- +
"(T container)"
+ +
+ "container.begin() +
+
+ +
+ "container.end() +
+
- + @@ -352,11 +352,11 @@ - + - - - + + +
@@ -368,30 +368,30 @@ convertible_to_string<T>
- +
"std::string{s}"
- -
- "{std::to_string(s)} noexcept" -
-
- -
- "{std::to_string(s)} -> std::same_as<std::string>" -
-
- +
"(T s)"
+ +
+ "{std::to_string(s) : rbrace; noexcept" +
+
+ +
+ "{std::to_string(s) : rbrace; -> std::same_as<std::string>" +
+
- + @@ -410,7 +410,7 @@ - + @@ -429,7 +429,7 @@ - + @@ -453,7 +453,7 @@ - + @@ -477,7 +477,7 @@ - + @@ -501,7 +501,7 @@ - + @@ -520,7 +520,7 @@ - + @@ -554,7 +554,7 @@ - + diff --git a/docs/test_cases/t00057_class.svg b/docs/test_cases/t00057_class.svg index 0a4db521..df1f625b 100644 --- a/docs/test_cases/t00057_class.svg +++ b/docs/test_cases/t00057_class.svg @@ -1,6 +1,6 @@ - + @@ -9,53 +9,53 @@ - - + + t00057_A - + - + a1 : int - - + + t00057_B - + - + b1 : int - - + + t00057_C - + - + c1 : int - - + + «union» @@ -63,73 +63,73 @@ - + - + d1 : int - + - + d2 : float - - + + t00057_E - + - + coordinates : t00057_E::(anonymous_739) - + - + e : int - + - + height : t00057_E::(anonymous_807) - - + + t00057_E::(coordinates) - + - + x : int - + - + y : int - - + + «union» @@ -137,105 +137,105 @@ - + - + t : double - + - + z : int - - + + t00057_G - + - + g1 : int - - + + t00057_R - + - + a : struct t00057_A - + - + b : t00057_B - + - + c : struct t00057_C * - + - + d : union t00057_D - + - + e : struct t00057_E * - + - + f : struct t00057_F * - + - + g : struct t00057_G * - - + + t00057_F - + - + f1 : int diff --git a/docs/test_cases/t00057_class_mermaid.svg b/docs/test_cases/t00057_class_mermaid.svg index 07bdad08..3c184d98 100644 --- a/docs/test_cases/t00057_class_mermaid.svg +++ b/docs/test_cases/t00057_class_mermaid.svg @@ -162,7 +162,7 @@ - + @@ -186,7 +186,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -234,7 +234,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -297,7 +297,7 @@ - + @@ -326,7 +326,7 @@ - + @@ -355,7 +355,7 @@ - + @@ -379,7 +379,7 @@ - + @@ -433,7 +433,7 @@ - + diff --git a/docs/test_cases/t00058.md b/docs/test_cases/t00058.md index efd05e44..849c68a7 100644 --- a/docs/test_cases/t00058.md +++ b/docs/test_cases/t00058.md @@ -13,6 +13,9 @@ diagrams: plantuml: after: - '{{ alias("same_as_first_type") }} ..> {{ alias("first_type") }}' + mermaid: + after: + - '{{ alias("same_as_first_type") }} ..> {{ alias("first_type") }}' ``` ## Source code File `tests/t00058/t00058.cc` @@ -378,7 +381,7 @@ struct R { "type": "int" } ], - "type": "clanguml::t00058::A" + "type": "A" } ], "type": "class" diff --git a/docs/test_cases/t00058_class.svg b/docs/test_cases/t00058_class.svg index d17750c0..c3187c28 100644 --- a/docs/test_cases/t00058_class.svg +++ b/docs/test_cases/t00058_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + first_type @@ -19,8 +19,8 @@ - - + + «concept» @@ -30,8 +30,8 @@ - - + + A @@ -40,15 +40,15 @@ - + - + a : std::vector<T> - - + + B @@ -57,22 +57,22 @@ - + - + b : std::vector<T> - + - + bb : P - - + + A @@ -81,8 +81,8 @@ - - + + A @@ -91,8 +91,8 @@ - - + + B @@ -101,26 +101,26 @@ - - + + R - + - + aa : A<int,int,double,std::string> - + - + bb : B<int,std::string,int,double,A<int,int>> diff --git a/docs/test_cases/t00058_class_mermaid.svg b/docs/test_cases/t00058_class_mermaid.svg index bd93f2d2..ae38dfc9 100644 --- a/docs/test_cases/t00058_class_mermaid.svg +++ b/docs/test_cases/t00058_class_mermaid.svg @@ -1,4 +1,4 @@ - + @@ -50,17 +50,18 @@ - - - - - - - - + + + + + + + + + - +
@@ -71,7 +72,7 @@ - +
@@ -126,7 +127,7 @@ - +
@@ -137,7 +138,7 @@ - +
@@ -148,9 +149,18 @@ + + + +
+ +
+
+
+
- + @@ -169,7 +179,7 @@ - + @@ -188,7 +198,7 @@ - + @@ -212,7 +222,7 @@ - + @@ -241,7 +251,7 @@ - + @@ -260,7 +270,7 @@ - + @@ -279,7 +289,7 @@ - + @@ -298,7 +308,7 @@ - + diff --git a/docs/test_cases/t00059.md b/docs/test_cases/t00059.md index 7d5f1293..31948576 100644 --- a/docs/test_cases/t00059.md +++ b/docs/test_cases/t00059.md @@ -167,6 +167,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "get_name", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -189,10 +190,12 @@ struct R { "line": 20, "translation_unit": "t00059.cc" }, + "template_parameters": [], "type": "std::string" }, { "access": "public", + "display_name": "get_sweetness", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -215,6 +218,7 @@ struct R { "line": 21, "translation_unit": "t00059.cc" }, + "template_parameters": [], "type": "float" } ], @@ -242,6 +246,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "get_name", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -264,10 +269,12 @@ struct R { "line": 26, "translation_unit": "t00059.cc" }, + "template_parameters": [], "type": "std::string" }, { "access": "public", + "display_name": "get_sweetness", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -290,6 +297,7 @@ struct R { "line": 27, "translation_unit": "t00059.cc" }, + "template_parameters": [], "type": "float" } ], @@ -317,6 +325,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "get_name", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -339,10 +348,12 @@ struct R { "line": 32, "translation_unit": "t00059.cc" }, + "template_parameters": [], "type": "std::string" }, { "access": "public", + "display_name": "get_bitterness", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -365,6 +376,7 @@ struct R { "line": 33, "translation_unit": "t00059.cc" }, + "template_parameters": [], "type": "float" } ], @@ -392,6 +404,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "get_name", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -414,10 +427,12 @@ struct R { "line": 38, "translation_unit": "t00059.cc" }, + "template_parameters": [], "type": "std::string" }, { "access": "public", + "display_name": "get_bitterness", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -440,6 +455,7 @@ struct R { "line": 39, "translation_unit": "t00059.cc" }, + "template_parameters": [], "type": "float" } ], @@ -467,6 +483,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "create_apple", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -489,10 +506,12 @@ struct R { "line": 44, "translation_unit": "t00059.cc" }, + "template_parameters": [], "type": "TA" }, { "access": "public", + "display_name": "create_orange", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -515,6 +534,7 @@ struct R { "line": 45, "translation_unit": "t00059.cc" }, + "template_parameters": [], "type": "TO" } ], @@ -566,13 +586,13 @@ struct R { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00059::gala_apple" + "type": "gala_apple" }, { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00059::valencia_orange" + "type": "valencia_orange" } ], "type": "class" @@ -601,13 +621,13 @@ struct R { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00059::empire_apple" + "type": "empire_apple" }, { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00059::lima_orange" + "type": "lima_orange" } ], "type": "class" diff --git a/docs/test_cases/t00059_class.svg b/docs/test_cases/t00059_class.svg index 56680197..4616d5f9 100644 --- a/docs/test_cases/t00059_class.svg +++ b/docs/test_cases/t00059_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + «concept» @@ -23,8 +23,8 @@ T{} t.get_name() - - + + «concept» @@ -36,8 +36,8 @@ t.get_sweetness() - - + + «concept» @@ -49,96 +49,96 @@ t.get_bitterness() - - + + gala_apple - + - + get_name() const : std::string - + - + get_sweetness() const : float - - + + empire_apple - + - + get_name() const : std::string - + - + get_sweetness() const : float - - + + lima_orange - + - + get_bitterness() const : float - + - + get_name() const : std::string - - + + valencia_orange - + - + get_bitterness() const : float - + - + get_name() const : std::string - - + + fruit_factory @@ -146,23 +146,23 @@ apple_c TA,orange_c TO - + - + create_apple() const : TA - + - + create_orange() const : TO - - + + fruit_factory @@ -171,8 +171,8 @@ - - + + fruit_factory @@ -181,26 +181,26 @@ - - + + R - + - + factory_1 : fruit_factory_1 - + - + factory_2 : fruit_factory_2 diff --git a/docs/test_cases/t00059_class_mermaid.svg b/docs/test_cases/t00059_class_mermaid.svg index 2df07a6f..511bb49b 100644 --- a/docs/test_cases/t00059_class_mermaid.svg +++ b/docs/test_cases/t00059_class_mermaid.svg @@ -50,10 +50,10 @@ - - - - + + + + @@ -64,7 +64,7 @@ - +
@@ -75,7 +75,7 @@ - +
@@ -86,7 +86,7 @@ - +
@@ -97,7 +97,7 @@ - +
@@ -198,11 +198,11 @@ - + - - - + + +
@@ -214,29 +214,29 @@ fruit_c<T>
- +
"T{}"
- -
- "t.get_name()" -
-
- +
"(T t)"
+ +
+ "t.get_name() +
+
- + - - - + + +
@@ -248,24 +248,24 @@ apple_c<T>
- -
- "t.get_sweetness()" -
-
- +
"(T t)"
+ +
+ "t.get_sweetness() +
+
- + - - - + + +
@@ -277,20 +277,20 @@ orange_c<T>
- -
- "t.get_bitterness()" -
-
- +
"(T t)"
+ +
+ "t.get_bitterness() +
+
- + @@ -319,7 +319,7 @@
- + @@ -348,7 +348,7 @@ - + @@ -377,7 +377,7 @@ - + @@ -406,7 +406,7 @@ - + @@ -435,7 +435,7 @@ - + @@ -454,7 +454,7 @@ - + @@ -473,7 +473,7 @@ - + diff --git a/docs/test_cases/t00060_class.svg b/docs/test_cases/t00060_class.svg index 5e8ec5a2..4c5394d4 100644 --- a/docs/test_cases/t00060_class.svg +++ b/docs/test_cases/t00060_class.svg @@ -1,6 +1,6 @@ - + @@ -9,40 +9,40 @@ - - + + A - - + + B - - + + C - - + + D - - + + G @@ -51,15 +51,15 @@ - + - + g : T - - + + H @@ -68,18 +68,18 @@ - + - + h : G<T> - + - + hh : P diff --git a/docs/test_cases/t00060_class_mermaid.svg b/docs/test_cases/t00060_class_mermaid.svg index bff4f4e1..ec266059 100644 --- a/docs/test_cases/t00060_class_mermaid.svg +++ b/docs/test_cases/t00060_class_mermaid.svg @@ -116,7 +116,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -154,7 +154,7 @@ - + @@ -173,7 +173,7 @@ - + @@ -192,7 +192,7 @@ - + @@ -216,7 +216,7 @@ - + diff --git a/docs/test_cases/t00061_class.svg b/docs/test_cases/t00061_class.svg index fa2ea2d1..b3ad5143 100644 --- a/docs/test_cases/t00061_class.svg +++ b/docs/test_cases/t00061_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A diff --git a/docs/test_cases/t00061_class_mermaid.svg b/docs/test_cases/t00061_class_mermaid.svg index a5d7765c..7c525d0f 100644 --- a/docs/test_cases/t00061_class_mermaid.svg +++ b/docs/test_cases/t00061_class_mermaid.svg @@ -52,7 +52,7 @@ - + diff --git a/docs/test_cases/t00062_class.svg b/docs/test_cases/t00062_class.svg index c2249cb4..4fc8840b 100644 --- a/docs/test_cases/t00062_class.svg +++ b/docs/test_cases/t00062_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,15 +19,15 @@ - + - + u : U & - - + + A @@ -36,15 +36,15 @@ - + - + u : U & - - + + A @@ -53,8 +53,8 @@ - - + + A @@ -63,15 +63,15 @@ - + - + u : U ** - - + + A @@ -80,15 +80,15 @@ - + - + u : U *** - - + + A @@ -97,15 +97,15 @@ - + - + u : U *** - - + + A @@ -114,15 +114,15 @@ - + - + u : U && - - + + A @@ -131,15 +131,15 @@ - + - + u : const U & - - + + A @@ -148,22 +148,22 @@ - + - + c : C & - + - + m : M C::* - - + + A @@ -172,22 +172,22 @@ - + - + c : C && - + - + m : M C::* - - + + A @@ -196,22 +196,22 @@ - + - + c : C & - + - + m : M C::* - - + + A @@ -220,15 +220,15 @@ - + - + c : C & - - + + A @@ -237,22 +237,22 @@ - + - + c : C && - + - + m : M C::* - - + + A @@ -261,22 +261,22 @@ - + - + c : C && - + - + mf : float C::* - - + + A @@ -285,22 +285,22 @@ - + - + c : C & - + - + m : M C::* - - + + A @@ -309,15 +309,15 @@ - + - + n : char[N] - - + + A @@ -326,15 +326,15 @@ - + - + n : std::vector<char> - - + + A @@ -343,15 +343,15 @@ - + - + klm : char[K][L][M] - - + + A @@ -360,15 +360,15 @@ - + - + u : bool - - + + A @@ -377,15 +377,15 @@ - + - + c : C<T> - - + + A @@ -394,22 +394,22 @@ - + - + args : std::tuple<Args...> - + - + c : C<T> - - + + A diff --git a/docs/test_cases/t00062_class_mermaid.svg b/docs/test_cases/t00062_class_mermaid.svg index 42475cb4..9d8441a5 100644 --- a/docs/test_cases/t00062_class_mermaid.svg +++ b/docs/test_cases/t00062_class_mermaid.svg @@ -306,7 +306,7 @@ - + @@ -330,7 +330,7 @@ - + @@ -354,7 +354,7 @@ - + @@ -373,7 +373,7 @@ - + @@ -397,7 +397,7 @@ - + @@ -421,7 +421,7 @@ - + @@ -445,7 +445,7 @@ - + @@ -469,7 +469,7 @@ - + @@ -493,7 +493,7 @@ - + @@ -522,7 +522,7 @@ - + @@ -551,7 +551,7 @@ - + @@ -580,7 +580,7 @@ - + @@ -604,7 +604,7 @@ - + @@ -633,7 +633,7 @@ - + @@ -662,7 +662,7 @@ - + @@ -691,7 +691,7 @@ - + @@ -715,7 +715,7 @@ - + @@ -739,7 +739,7 @@ - + @@ -763,7 +763,7 @@ - + @@ -787,7 +787,7 @@ - + @@ -811,7 +811,7 @@ - + @@ -840,7 +840,7 @@ - + diff --git a/docs/test_cases/t00063_class.svg b/docs/test_cases/t00063_class.svg index 7dfe2eed..7de91621 100644 --- a/docs/test_cases/t00063_class.svg +++ b/docs/test_cases/t00063_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A diff --git a/docs/test_cases/t00063_class_mermaid.svg b/docs/test_cases/t00063_class_mermaid.svg index cf132990..1012aa59 100644 --- a/docs/test_cases/t00063_class_mermaid.svg +++ b/docs/test_cases/t00063_class_mermaid.svg @@ -52,7 +52,7 @@ - + diff --git a/docs/test_cases/t00064.md b/docs/test_cases/t00064.md index 1df262d4..55704b88 100644 --- a/docs/test_cases/t00064.md +++ b/docs/test_cases/t00064.md @@ -271,7 +271,7 @@ public: "template_parameters": [] } ], - "type": "clanguml::t00064::type_list" + "type": "type_list" } ], "type": "class" @@ -407,7 +407,7 @@ public: "template_parameters": [] } ], - "type": "clanguml::t00064::type_list" + "type": "type_list" }, { "is_variadic": false, @@ -420,7 +420,7 @@ public: "template_parameters": [] } ], - "type": "clanguml::t00064::type_list" + "type": "type_list" } ], "type": "class" @@ -478,7 +478,7 @@ public: "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00064::type_group_pair_it,clanguml::t00064::type_list>::value_type" + "type": "type_group_pair_it,type_list>::value_type" } ], "type": "class" @@ -496,6 +496,7 @@ public: "methods": [ { "access": "public", + "display_name": "get", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -523,10 +524,12 @@ public: "line": 44, "translation_unit": "t00064.cc" }, + "template_parameters": [], "type": "ref_t" }, { "access": "public", + "display_name": "getp", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -554,10 +557,12 @@ public: "line": 46, "translation_unit": "t00064.cc" }, + "template_parameters": [], "type": "const value_type *" }, { "access": "public", + "display_name": "find", "is_const": false, "is_consteval": false, "is_constexpr": true, @@ -585,6 +590,7 @@ public: "line": 48, "translation_unit": "t00064.cc" }, + "template_parameters": [], "type": "unsigned int" } ], @@ -614,7 +620,7 @@ public: "template_parameters": [] } ], - "type": "clanguml::t00064::type_list" + "type": "type_list" }, { "is_variadic": false, @@ -627,7 +633,7 @@ public: "template_parameters": [] } ], - "type": "clanguml::t00064::type_list" + "type": "type_list" } ], "type": "class" @@ -722,7 +728,7 @@ public: "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00064::A" + "type": "A" }, { "is_variadic": false, @@ -798,19 +804,19 @@ public: "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00064::A" + "type": "A" }, { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00064::B" + "type": "B" }, { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00064::C" + "type": "C" } ], "type": "class" @@ -852,7 +858,7 @@ public: "type": "double" } ], - "type": "clanguml::t00064::type_list" + "type": "type_list" }, { "is_variadic": false, @@ -877,7 +883,7 @@ public: "type": "clanguml::t00064::C" } ], - "type": "clanguml::t00064::type_list" + "type": "type_list" } ], "type": "class" diff --git a/docs/test_cases/t00064_class.svg b/docs/test_cases/t00064_class.svg index f8538d7b..171d69af 100644 --- a/docs/test_cases/t00064_class.svg +++ b/docs/test_cases/t00064_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + type_list @@ -19,8 +19,8 @@ - - + + type_list @@ -29,8 +29,8 @@ - - + + type_list @@ -39,8 +39,8 @@ - - + + type_list @@ -49,8 +49,8 @@ - - + + head @@ -59,8 +59,8 @@ - - + + type_list @@ -69,8 +69,8 @@ - - + + type_list @@ -79,8 +79,8 @@ - - + + type_list @@ -89,8 +89,8 @@ - - + + type_group_pair @@ -99,15 +99,15 @@ - + - + size : const size_t - - + + optional_ref @@ -116,8 +116,8 @@ - - + + optional_ref @@ -126,8 +126,8 @@ - - + + type_group_pair_it @@ -135,54 +135,54 @@ It,type_list<First...>,type_list<Second...> - + - + find(const value_type & v) constexpr : unsigned int - + - + get(unsigned int i) : ref_t - + - + getp(unsigned int i) : const value_type * - - + + A - - + + B - - + + C - - + + type_list @@ -191,8 +191,8 @@ - - + + type_list @@ -201,8 +201,8 @@ - - + + type_list @@ -211,8 +211,8 @@ - - + + type_group_pair @@ -221,30 +221,30 @@ - - + + R - + - + abc : type_group_pair<type_list<float,double>,type_list<A,B,C>> - + - + aboolint : type_list<A,bool,int> - - + + type_group_pair @@ -253,8 +253,8 @@ - - + + type_group_pair_it @@ -263,8 +263,8 @@ - - + + head diff --git a/docs/test_cases/t00064_class_mermaid.svg b/docs/test_cases/t00064_class_mermaid.svg index 92eb40c9..1a88944d 100644 --- a/docs/test_cases/t00064_class_mermaid.svg +++ b/docs/test_cases/t00064_class_mermaid.svg @@ -390,7 +390,7 @@ - + @@ -409,7 +409,7 @@ - + @@ -428,7 +428,7 @@ - + @@ -447,7 +447,7 @@ - + @@ -466,7 +466,7 @@ - + @@ -485,7 +485,7 @@ - + @@ -504,7 +504,7 @@ - + @@ -523,7 +523,7 @@ - + @@ -542,7 +542,7 @@ - + @@ -566,7 +566,7 @@ - + @@ -585,7 +585,7 @@ - + @@ -604,7 +604,7 @@ - + @@ -638,7 +638,7 @@ - + @@ -657,7 +657,7 @@ - + @@ -676,7 +676,7 @@ - + @@ -695,7 +695,7 @@ - + @@ -714,7 +714,7 @@ - + @@ -733,7 +733,7 @@ - + @@ -752,7 +752,7 @@ - + @@ -771,7 +771,7 @@ - + @@ -800,7 +800,7 @@ - + @@ -819,7 +819,7 @@ - + @@ -838,7 +838,7 @@ - + diff --git a/docs/test_cases/t00065.md b/docs/test_cases/t00065.md index 8cdc37ed..141c7de0 100644 --- a/docs/test_cases/t00065.md +++ b/docs/test_cases/t00065.md @@ -120,7 +120,7 @@ struct AImpl { }; "elements": [ { "bases": [], - "display_name": "detail::AImpl", + "display_name": "AImpl", "id": "674757414308736755", "is_abstract": false, "is_nested": false, @@ -291,6 +291,7 @@ struct AImpl { }; "methods": [ { "access": "public", + "display_name": "B", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -313,10 +314,12 @@ struct AImpl { }; "line": 8, "translation_unit": "t00065.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "b", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -339,6 +342,7 @@ struct AImpl { }; "line": 9, "translation_unit": "t00065.cc" }, + "template_parameters": [], "type": "void" } ], @@ -502,7 +506,7 @@ struct AImpl { }; "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00065::B" + "type": "B" } ], "type": "class" @@ -531,7 +535,7 @@ struct AImpl { }; "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00065::B" + "type": "B" } ], "type": "class" diff --git a/docs/test_cases/t00065_class.svg b/docs/test_cases/t00065_class.svg index 34e07855..1d3f720c 100644 --- a/docs/test_cases/t00065_class.svg +++ b/docs/test_cases/t00065_class.svg @@ -1,6 +1,6 @@ - + - + @@ -9,20 +9,20 @@ - + module1 - - - submodule1a - - - module2 - - - concepts - - + + + submodule1a + + + module2 + + + concepts + + ABC @@ -32,8 +32,8 @@ c - - + + XYZ @@ -43,216 +43,216 @@ z - - - - - A - - + + + + + A + + - - - + + + - - abc : ABC + + abc : ABC - - - + + + - - pimpl : detail::AImpl * + + pimpl : detail::AImpl * - - - + + + - - xyz : XYZ + + xyz : XYZ - - - - - detail::AImpl - - + + + + + AImpl + + - - - - - B - + + + + + B + - - - + + + - - B() = default : void + + B() = default : void - - - - + + + + - - b() : void + + b() : void - - - - - - C - - T - - + + + + + + C + + T + + - - - + + + - - t : T * + + t : T * - - - - - C - - int - - + + + + + C + + int + + - - - - - D - - bconcept T - - + + + + + D + + bconcept T + + - - - + + + - - c : C<int> + + c : C<int> - - - + + + - - t : T + + t : T - - - - - C - - B - - + + + + + C + + B + + - - - - - D - - B - - + + + + + D + + B + + - - - - - «concept» - bconcept - - T - - (T t) - - T{} - t.b() + + + + + «concept» + bconcept + + T + + (T t) + + T{} + t.b() - - - - - R - - + + + + + R + + - - - + + + - - a : A * + + a : A * - - - + + + - - c : C<B> + + c : C<B> - - - + + + - - d : D<B> + + d : D<B> - - - - abc - - - - xyz - - - - pimpl - - - - - T - - - +c - - - - - - - - - - - +a - - - +c - - - +d + + + + abc + + + + xyz + + + + pimpl + + + + + T + + + +c + + + + + + + + + + + +a + + + +c + + + +d diff --git a/docs/test_cases/t00065_class_mermaid.svg b/docs/test_cases/t00065_class_mermaid.svg index 239792a4..dbc1b14b 100644 --- a/docs/test_cases/t00065_class_mermaid.svg +++ b/docs/test_cases/t00065_class_mermaid.svg @@ -210,7 +210,7 @@ - + @@ -229,7 +229,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -297,7 +297,7 @@ - + @@ -331,11 +331,11 @@ - + - +
@@ -352,20 +352,20 @@ "T{}"
- -
- "t.b()" -
-
- +
"(T t)"
+ +
+ "t.b() +
+
- + @@ -394,7 +394,7 @@ - + @@ -418,7 +418,7 @@ - + @@ -437,7 +437,7 @@ - + @@ -466,7 +466,7 @@ - + @@ -485,7 +485,7 @@ - + @@ -504,7 +504,7 @@ - + diff --git a/docs/test_cases/t00066.md b/docs/test_cases/t00066.md index b0335cc5..cf124f52 100644 --- a/docs/test_cases/t00066.md +++ b/docs/test_cases/t00066.md @@ -229,6 +229,7 @@ int A::static_int = 1; "methods": [ { "access": "public", + "display_name": "A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -251,10 +252,12 @@ int A::static_int = 1; "line": 9, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -282,10 +285,12 @@ int A::static_int = 1; "line": 10, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -313,10 +318,12 @@ int A::static_int = 1; "line": 14, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -344,10 +351,12 @@ int A::static_int = 1; "line": 15, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "~A", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -370,10 +379,12 @@ int A::static_int = 1; "line": 16, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "basic_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -396,10 +407,12 @@ int A::static_int = 1; "line": 18, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "static_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -422,10 +435,12 @@ int A::static_int = 1; "line": 19, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "const_method", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -448,10 +463,12 @@ int A::static_int = 1; "line": 20, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "auto_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -474,10 +491,12 @@ int A::static_int = 1; "line": 21, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "operator++", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -500,10 +519,12 @@ int A::static_int = 1; "line": 23, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "A &" }, { "access": "public", + "display_name": "operator=", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -531,10 +552,12 @@ int A::static_int = 1; "line": 29, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "A &" }, { "access": "public", + "display_name": "operator=", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -562,10 +585,12 @@ int A::static_int = 1; "line": 30, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "A &" }, { "access": "public", + "display_name": "size", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -588,10 +613,12 @@ int A::static_int = 1; "line": 32, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "std::size_t" }, { "access": "public", + "display_name": "double_int", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -619,10 +646,12 @@ int A::static_int = 1; "line": 34, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "sum", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -654,10 +683,12 @@ int A::static_int = 1; "line": 35, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "default_int", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -686,10 +717,12 @@ int A::static_int = 1; "line": 37, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "default_string", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -722,10 +755,12 @@ int A::static_int = 1; "line": 38, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "std::string" }, { "access": "public", + "display_name": "create_from_int", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -753,10 +788,12 @@ int A::static_int = 1; "line": 43, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "A" }, { "access": "protected", + "display_name": "protected_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -779,10 +816,12 @@ int A::static_int = 1; "line": 51, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "void" }, { "access": "private", + "display_name": "private_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -805,6 +844,7 @@ int A::static_int = 1; "line": 60, "translation_unit": "t00066.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00066_class.svg b/docs/test_cases/t00066_class.svg index 67b9f7a9..9229314b 100644 --- a/docs/test_cases/t00066_class.svg +++ b/docs/test_cases/t00066_class.svg @@ -1,6 +1,6 @@ - + @@ -9,222 +9,222 @@ - - + + A - + - + public_member : int - + - + protected_member : int - + - + private_member : int - + - + a_ : int - + - + b_ : int - + - + c_ : int - + - + static_int : int - + - + static_const_int : const int - + - + auto_member : const unsigned long - + - + A() = default : void - + - + A(int i) : void - + - + A(A &&) = default : void - + - + A(const A &) = deleted : void - + - + ~A() = default : void - + - + basic_method() : void - + - + static_method() : int - + - + const_method() const : void - + - + auto_method() : int - + - + operator++() : A & - + - + operator=(A && other) noexcept : A & - + - + operator=(A & other) noexcept : A & - + - + size() const : std::size_t - + - + double_int(const int i) : int - + - + sum(const double a, const double b) : int - + - + default_int(int i = 12) : int - + - + default_string(int i, std::string s = "abc") : std::string - + - + create_from_int(int i) : A - + - + protected_method() : void - + - + private_method() : void - + - + compare : std::function<bool (const int)> diff --git a/docs/test_cases/t00066_class_mermaid.svg b/docs/test_cases/t00066_class_mermaid.svg index 81afb0fc..7a90af17 100644 --- a/docs/test_cases/t00066_class_mermaid.svg +++ b/docs/test_cases/t00066_class_mermaid.svg @@ -52,7 +52,7 @@ - + diff --git a/docs/test_cases/t00067.md b/docs/test_cases/t00067.md index caf5131f..43f43fc0 100644 --- a/docs/test_cases/t00067.md +++ b/docs/test_cases/t00067.md @@ -232,6 +232,7 @@ int A::static_int = 1; "methods": [ { "access": "public", + "display_name": "basic_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -254,10 +255,12 @@ int A::static_int = 1; "line": 17, "translation_unit": "t00067.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "const_method", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -280,10 +283,12 @@ int A::static_int = 1; "line": 19, "translation_unit": "t00067.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "auto_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -306,10 +311,12 @@ int A::static_int = 1; "line": 20, "translation_unit": "t00067.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "size", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -332,10 +339,12 @@ int A::static_int = 1; "line": 31, "translation_unit": "t00067.cc" }, + "template_parameters": [], "type": "std::size_t" }, { "access": "public", + "display_name": "double_int", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -363,10 +372,12 @@ int A::static_int = 1; "line": 33, "translation_unit": "t00067.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "sum", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -398,10 +409,12 @@ int A::static_int = 1; "line": 34, "translation_unit": "t00067.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "default_int", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -430,10 +443,12 @@ int A::static_int = 1; "line": 36, "translation_unit": "t00067.cc" }, + "template_parameters": [], "type": "int" }, { "access": "public", + "display_name": "default_string", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -466,10 +481,12 @@ int A::static_int = 1; "line": 37, "translation_unit": "t00067.cc" }, + "template_parameters": [], "type": "std::string" }, { "access": "protected", + "display_name": "protected_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -492,10 +509,12 @@ int A::static_int = 1; "line": 50, "translation_unit": "t00067.cc" }, + "template_parameters": [], "type": "void" }, { "access": "private", + "display_name": "private_method", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -518,6 +537,7 @@ int A::static_int = 1; "line": 59, "translation_unit": "t00067.cc" }, + "template_parameters": [], "type": "void" } ], diff --git a/docs/test_cases/t00067_class.svg b/docs/test_cases/t00067_class.svg index 8354db62..ce454df6 100644 --- a/docs/test_cases/t00067_class.svg +++ b/docs/test_cases/t00067_class.svg @@ -1,6 +1,6 @@ - + @@ -9,152 +9,152 @@ - - + + A - + - + auto_method() : int - + - + basic_method() : void - + - + const_method() const : void - + - + default_int(int i = 12) : int - + - + default_string(int i, std::string s = "abc") : std::string - + - + double_int(const int i) : int - + - + private_method() : void - + - + protected_method() : void - + - + size() const : std::size_t - + - + sum(const double a, const double b) : int - + - + a_ : int - + - + auto_member : const unsigned long - + - + b_ : int - + - + c_ : int - + - + compare : std::function<bool (const int)> - + - + private_member : int - + - + protected_member : int - + - + public_member : int - + - + static_const_int : const int - + - + static_int : int diff --git a/docs/test_cases/t00067_class_mermaid.svg b/docs/test_cases/t00067_class_mermaid.svg index b9c2272c..30694236 100644 --- a/docs/test_cases/t00067_class_mermaid.svg +++ b/docs/test_cases/t00067_class_mermaid.svg @@ -52,7 +52,7 @@ - + diff --git a/docs/test_cases/t00068_r0_class.svg b/docs/test_cases/t00068_r0_class.svg index d88cbe7e..fa29620b 100644 --- a/docs/test_cases/t00068_r0_class.svg +++ b/docs/test_cases/t00068_r0_class.svg @@ -1,6 +1,6 @@ - + @@ -10,26 +10,26 @@ AAA context of radius 0 - - + + AAA - + - + akind : AKind - + - + bb : BB * diff --git a/docs/test_cases/t00068_r0_class_mermaid.svg b/docs/test_cases/t00068_r0_class_mermaid.svg index eb2dfa19..53857e80 100644 --- a/docs/test_cases/t00068_r0_class_mermaid.svg +++ b/docs/test_cases/t00068_r0_class_mermaid.svg @@ -53,7 +53,7 @@ - + diff --git a/docs/test_cases/t00068_r1_class.svg b/docs/test_cases/t00068_r1_class.svg index aa51840e..3c0b229a 100644 --- a/docs/test_cases/t00068_r1_class.svg +++ b/docs/test_cases/t00068_r1_class.svg @@ -1,6 +1,6 @@ - + @@ -10,23 +10,23 @@ AAA context of radius 1 - - + + BB - + - + b : std::vector<B> - - + + AKind @@ -36,49 +36,49 @@ ThreeA - - + + AA - - + + AAA - + - + akind : AKind - + - + bb : BB * - - + + R - + - + aaa : AAA * diff --git a/docs/test_cases/t00068_r1_class_mermaid.svg b/docs/test_cases/t00068_r1_class_mermaid.svg index 745b011d..a497beb5 100644 --- a/docs/test_cases/t00068_r1_class_mermaid.svg +++ b/docs/test_cases/t00068_r1_class_mermaid.svg @@ -101,7 +101,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -159,7 +159,7 @@ - + @@ -178,7 +178,7 @@ - + @@ -207,7 +207,7 @@ - + diff --git a/docs/test_cases/t00068_r2_class.svg b/docs/test_cases/t00068_r2_class.svg index cd4a1c8e..4f4c40ef 100644 --- a/docs/test_cases/t00068_r2_class.svg +++ b/docs/test_cases/t00068_r2_class.svg @@ -1,6 +1,6 @@ - + @@ -10,31 +10,31 @@ AAA context of radius 2 - - + + B - - + + BB - + - + b : std::vector<B> - - + + AKind @@ -44,72 +44,72 @@ ThreeA - - + + A - - + + AA - - + + AAA - + - + akind : AKind - + - + bb : BB * - - + + R - + - + aaa : AAA * - - + + RR - + - + r : std::shared_ptr<R> diff --git a/docs/test_cases/t00068_r2_class_mermaid.svg b/docs/test_cases/t00068_r2_class_mermaid.svg index 9bb3ee6f..152b2363 100644 --- a/docs/test_cases/t00068_r2_class_mermaid.svg +++ b/docs/test_cases/t00068_r2_class_mermaid.svg @@ -135,7 +135,7 @@ - + @@ -154,7 +154,7 @@ - + @@ -178,7 +178,7 @@ - + @@ -212,7 +212,7 @@ - + @@ -231,7 +231,7 @@ - + @@ -250,7 +250,7 @@ - + @@ -279,7 +279,7 @@ - + @@ -303,7 +303,7 @@ - + diff --git a/docs/test_cases/t00069.md b/docs/test_cases/t00069.md index e544d504..a68a1adf 100644 --- a/docs/test_cases/t00069.md +++ b/docs/test_cases/t00069.md @@ -126,6 +126,7 @@ private: "methods": [ { "access": "public", + "display_name": "generator", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -153,10 +154,12 @@ private: "line": 11, "translation_unit": "t00069.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "~generator", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -179,6 +182,7 @@ private: "line": 16, "translation_unit": "t00069.cc" }, + "template_parameters": [], "type": "void" } ], @@ -238,6 +242,7 @@ private: "methods": [ { "access": "public", + "display_name": "get_return_object", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -260,10 +265,12 @@ private: "line": 22, "translation_unit": "t00069.cc" }, + "template_parameters": [], "type": "generator" }, { "access": "public", + "display_name": "initial_suspend", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -286,10 +293,12 @@ private: "line": 26, "translation_unit": "t00069.cc" }, + "template_parameters": [], "type": "std::suspend_always" }, { "access": "public", + "display_name": "final_suspend", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -312,10 +321,12 @@ private: "line": 28, "translation_unit": "t00069.cc" }, + "template_parameters": [], "type": "std::suspend_always" }, { "access": "public", + "display_name": "unhandled_exception", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -338,10 +349,12 @@ private: "line": 30, "translation_unit": "t00069.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "return_void", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -364,10 +377,12 @@ private: "line": 39, "translation_unit": "t00069.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "yield_value", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -389,6 +404,14 @@ private: "type": "From &&" } ], + "template_parameters": [ + { + "is_variadic": false, + "kind": "template_type", + "name": "From", + "template_parameters": [] + } + ], "type": "std::suspend_always" } ], @@ -458,6 +481,7 @@ private: "methods": [ { "access": "public", + "display_name": "iota", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -480,10 +504,12 @@ private: "line": 50, "translation_unit": "t00069.cc" }, + "template_parameters": [], "type": "clanguml::t00069::generator" }, { "access": "public", + "display_name": "seed", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -506,6 +532,7 @@ private: "line": 52, "translation_unit": "t00069.cc" }, + "template_parameters": [], "type": "clanguml::t00069::generator" } ], diff --git a/docs/test_cases/t00069_class.svg b/docs/test_cases/t00069_class.svg index c65f3232..cccbeff7 100644 --- a/docs/test_cases/t00069_class.svg +++ b/docs/test_cases/t00069_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + generator @@ -18,96 +18,96 @@ T - + - + generator(handle_type h) : void - + - + ~generator() : void - + - + full_ : bool - + - + h_ : handle_type - - + + generator::promise_type - + - + final_suspend() noexcept : std::suspend_always - + - + get_return_object() : generator<T> - + - + initial_suspend() : std::suspend_always - + - + return_void() : void - + - + unhandled_exception() : void yield_value<std::convertible_to From>(From && from) : std::suspend_always - + - + exception_ : std::exception_ptr - + - + value_ : T - - + + generator @@ -116,33 +116,33 @@ - - + + A - + - + iota() [coroutine] : generator<unsigned long> - + - + seed() [coroutine] : generator<unsigned long> - + - + counter_ : unsigned long diff --git a/docs/test_cases/t00069_class_mermaid.svg b/docs/test_cases/t00069_class_mermaid.svg index 58ff002e..c0f5772b 100644 --- a/docs/test_cases/t00069_class_mermaid.svg +++ b/docs/test_cases/t00069_class_mermaid.svg @@ -90,7 +90,7 @@ - + @@ -129,7 +129,7 @@ - + @@ -188,7 +188,7 @@ - + @@ -207,7 +207,7 @@ - + diff --git a/docs/test_cases/t00070.md b/docs/test_cases/t00070.md index 047fa287..ffc7cc62 100644 --- a/docs/test_cases/t00070.md +++ b/docs/test_cases/t00070.md @@ -211,6 +211,7 @@ class BBBB { }; "methods": [ { "access": "private", + "display_name": "get", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -233,6 +234,7 @@ class BBBB { }; "line": 7, "translation_unit": "t00070.cc" }, + "template_parameters": [], "type": "int" } ], diff --git a/docs/test_cases/t00070_class.svg b/docs/test_cases/t00070_class.svg index 2cec7afa..4768b86b 100644 --- a/docs/test_cases/t00070_class.svg +++ b/docs/test_cases/t00070_class.svg @@ -1,6 +1,6 @@ - + @@ -9,16 +9,16 @@ - - + + B - - + + BB @@ -27,15 +27,15 @@ - + - + t : T - - + + BBB @@ -44,26 +44,26 @@ bbb2 - - + + A - + - + get() : int - + - + a : int diff --git a/docs/test_cases/t00070_class_mermaid.svg b/docs/test_cases/t00070_class_mermaid.svg index 84d9c98a..d57069ac 100644 --- a/docs/test_cases/t00070_class_mermaid.svg +++ b/docs/test_cases/t00070_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -95,7 +95,7 @@ - + @@ -124,7 +124,7 @@ - + diff --git a/docs/test_cases/t00071.md b/docs/test_cases/t00071.md index abf6dfcd..e7cedd2a 100644 --- a/docs/test_cases/t00071.md +++ b/docs/test_cases/t00071.md @@ -187,7 +187,7 @@ class D { }; "bbb1", "bbb2" ], - "display_name": "detail::BBB", + "display_name": "BBB", "id": "1625078061541942293", "is_nested": false, "module": { @@ -354,7 +354,7 @@ class D { }; "ccc1", "ccc2" ], - "display_name": "detail::CCC", + "display_name": "CCC", "id": "931278702894205804", "is_nested": false, "module": { @@ -401,6 +401,7 @@ class D { }; "methods": [ { "access": "private", + "display_name": "get", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -423,6 +424,7 @@ class D { }; "line": 7, "translation_unit": "t00071.cc" }, + "template_parameters": [], "type": "int" } ], diff --git a/docs/test_cases/t00071_class.svg b/docs/test_cases/t00071_class.svg index 07e03127..24945452 100644 --- a/docs/test_cases/t00071_class.svg +++ b/docs/test_cases/t00071_class.svg @@ -1,6 +1,6 @@ - + - + @@ -9,166 +9,166 @@ - + app - + lib1 - - - mod1 - - - mod2 - - - lib2 - - + + + mod1 + + + mod2 + + + lib2 + + A - + - + get() : int - + - + a : int - - - - - B - - + + + + + B + + - - - - - BB - - T - - + + + + + BB + + T + + - - - + + + - - t : T + + t : T - - - - - detail::BBB - - bbb1 - bbb2 - + + + + + BBB + + bbb1 + bbb2 + - - - - - D - - + + + + + D + + - - - - - E - - + + + + + E + + - - - - - C - - + + + + + C + + - - - - - CC - - T - - + + + + + CC + + T + + - - - + + + - - t : T + + t : T - - - - - detail::CCC - - ccc1 - ccc2 - + + + + + CCC + + ccc1 + ccc2 + - - - - - R - - + + + + + R + + - - - + + + - - a : A * + + a : A * - - - + + + - - b : B * + + b : B * - - - + + + - - c : C * + + c : C * - - - -a - - - -b - - - -c + + + -a + + + -b + + + -c diff --git a/docs/test_cases/t00071_class_mermaid.svg b/docs/test_cases/t00071_class_mermaid.svg index 5997bb50..5b1d9718 100644 --- a/docs/test_cases/t00071_class_mermaid.svg +++ b/docs/test_cases/t00071_class_mermaid.svg @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -133,7 +133,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -181,7 +181,7 @@ - + @@ -200,7 +200,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -243,7 +243,7 @@ - + @@ -272,7 +272,7 @@ - + @@ -301,7 +301,7 @@ - + diff --git a/docs/test_cases/t00072.md b/docs/test_cases/t00072.md index 1e0137d5..662c3002 100644 --- a/docs/test_cases/t00072.md +++ b/docs/test_cases/t00072.md @@ -180,7 +180,7 @@ class D { }; "bbb1", "bbb2" ], - "display_name": "detail::BBB", + "display_name": "BBB", "id": "610293402618118513", "is_nested": false, "module": { @@ -347,7 +347,7 @@ class D { }; "ccc1", "ccc2" ], - "display_name": "detail::CCC", + "display_name": "CCC", "id": "448885573685763285", "is_nested": false, "module": { @@ -394,6 +394,7 @@ class D { }; "methods": [ { "access": "private", + "display_name": "get", "is_const": false, "is_consteval": false, "is_constexpr": false, @@ -416,6 +417,7 @@ class D { }; "line": 9, "translation_unit": "t00072.cc" }, + "template_parameters": [], "type": "int" } ], diff --git a/docs/test_cases/t00072_class.svg b/docs/test_cases/t00072_class.svg index 25d24cce..ee92ed73 100644 --- a/docs/test_cases/t00072_class.svg +++ b/docs/test_cases/t00072_class.svg @@ -1,6 +1,6 @@ - + @@ -9,53 +9,53 @@ - + app - + :lib1 - + mod1 - + mod2 - + :lib2 - - + + A - + - + get() : int - + - + a : int - - + + B - - + + BB @@ -64,49 +64,49 @@ - + - + t : T - - - - - detail::BBB - - bbb1 - bbb2 - + + + + + BBB + + bbb1 + bbb2 + - - + + D - - + + E - - + + C - - + + CC @@ -115,22 +115,22 @@ - + - + t : T - - - - - detail::CCC - - ccc1 - ccc2 - + + + + + CCC + + ccc1 + ccc2 + diff --git a/docs/test_cases/t00072_class_mermaid.svg b/docs/test_cases/t00072_class_mermaid.svg index a5ff8a6d..9c4b5889 100644 --- a/docs/test_cases/t00072_class_mermaid.svg +++ b/docs/test_cases/t00072_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -95,7 +95,7 @@ - + @@ -124,7 +124,7 @@ - + @@ -143,7 +143,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -181,7 +181,7 @@ - + @@ -205,7 +205,7 @@ - + @@ -234,7 +234,7 @@ - + diff --git a/docs/test_cases/t00073.md b/docs/test_cases/t00073.md index 3a6ef4fc..acca766c 100644 --- a/docs/test_cases/t00073.md +++ b/docs/test_cases/t00073.md @@ -83,6 +83,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "handle", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -110,10 +111,12 @@ struct R { "line": 5, "translation_unit": "t00073.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "operator()", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -141,6 +144,7 @@ struct R { "line": 6, "translation_unit": "t00073.cc" }, + "template_parameters": [], "type": "void" } ], @@ -190,6 +194,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "handle", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -217,10 +222,12 @@ struct R { "line": 11, "translation_unit": "t00073.cc" }, + "template_parameters": [], "type": "void" }, { "access": "public", + "display_name": "operator()", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -248,6 +255,7 @@ struct R { "line": 12, "translation_unit": "t00073.cc" }, + "template_parameters": [], "type": "void" } ], @@ -328,13 +336,13 @@ struct R { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00073::AHandler" + "type": "AHandler" }, { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00073::BHandler" + "type": "BHandler" } ], "type": "class" diff --git a/docs/test_cases/t00073_class.svg b/docs/test_cases/t00073_class.svg index dfecdb9d..cb0aceb5 100644 --- a/docs/test_cases/t00073_class.svg +++ b/docs/test_cases/t00073_class.svg @@ -1,6 +1,6 @@ - + @@ -9,70 +9,70 @@ - - + + A - - + + AHandler - + - + operator()(A & a) const : void - + - + handle(A & a) const : void - - + + B - - + + BHandler - + - + operator()(B & b) const : void - + - + handle(B & b) const : void - - + + Overload @@ -81,8 +81,8 @@ - - + + Overload @@ -91,19 +91,19 @@ - - + + R - + - + dispatch : Overload<AHandler,BHandler> diff --git a/docs/test_cases/t00073_class_mermaid.svg b/docs/test_cases/t00073_class_mermaid.svg index 91b6ffe4..db65ea53 100644 --- a/docs/test_cases/t00073_class_mermaid.svg +++ b/docs/test_cases/t00073_class_mermaid.svg @@ -122,7 +122,7 @@ - + @@ -141,7 +141,7 @@ - + @@ -170,7 +170,7 @@ - + @@ -189,7 +189,7 @@ - + @@ -218,7 +218,7 @@ - + @@ -237,7 +237,7 @@ - + @@ -256,7 +256,7 @@ - + diff --git a/docs/test_cases/t00074_class.svg b/docs/test_cases/t00074_class.svg index 939d7b89..5f2833df 100644 --- a/docs/test_cases/t00074_class.svg +++ b/docs/test_cases/t00074_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + «concept» @@ -20,8 +20,8 @@ - - + + «concept» @@ -31,8 +31,8 @@ - - + + «concept» diff --git a/docs/test_cases/t00074_class_mermaid.svg b/docs/test_cases/t00074_class_mermaid.svg index f747dfd1..008c3834 100644 --- a/docs/test_cases/t00074_class_mermaid.svg +++ b/docs/test_cases/t00074_class_mermaid.svg @@ -78,7 +78,7 @@ - + @@ -97,7 +97,7 @@ - + @@ -116,7 +116,7 @@ - + diff --git a/docs/test_cases/t00075.md b/docs/test_cases/t00075.md index 1c14d583..a5917295 100644 --- a/docs/test_cases/t00075.md +++ b/docs/test_cases/t00075.md @@ -74,7 +74,7 @@ struct R { "display_name": "ns2", "elements": [ { - "display_name": "ns1::ns2::C", + "display_name": "C", "id": "1809332102026994985", "name": "C", "namespace": "clanguml::t00075::ns1::ns2", @@ -101,7 +101,7 @@ struct R { "k1", "k2" ], - "display_name": "ns1::ns2::E", + "display_name": "E", "id": "1495076068471344273", "is_nested": false, "name": "E", @@ -116,7 +116,7 @@ struct R { }, { "bases": [], - "display_name": "ns1::ns2::A", + "display_name": "A", "id": "939187921829983364", "is_abstract": false, "is_nested": false, @@ -127,6 +127,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "e", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -149,6 +150,7 @@ struct R { "line": 15, "translation_unit": "t00075.cc" }, + "template_parameters": [], "type": "E" } ], @@ -165,7 +167,7 @@ struct R { }, { "bases": [], - "display_name": "ns1::ns2::B", + "display_name": "B", "id": "707211578295440427", "is_abstract": false, "is_nested": false, @@ -176,6 +178,7 @@ struct R { "methods": [ { "access": "public", + "display_name": "e", "is_const": true, "is_consteval": false, "is_constexpr": false, @@ -198,6 +201,7 @@ struct R { "line": 20, "translation_unit": "t00075.cc" }, + "template_parameters": [], "type": "E" } ], @@ -214,7 +218,7 @@ struct R { }, { "bases": [], - "display_name": "ns1::ns2::ABE", + "display_name": "ABE", "id": "783353028058924890", "is_abstract": false, "is_nested": false, @@ -256,7 +260,7 @@ struct R { }, { "bases": [], - "display_name": "ns1::ns2::ABE", + "display_name": "ABE", "id": "1387241450840584649", "is_abstract": false, "is_nested": false, @@ -278,14 +282,14 @@ struct R { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00075::ns1::ns2::A" + "type": "ns1::ns2::A" } ], "type": "class" }, { "bases": [], - "display_name": "ns1::ns2::ABE", + "display_name": "ABE", "id": "1119831184809815406", "is_abstract": false, "is_nested": false, @@ -307,14 +311,14 @@ struct R { "is_variadic": false, "kind": "argument", "template_parameters": [], - "type": "clanguml::t00075::ns1::ns2::B" + "type": "ns1::ns2::B" } ], "type": "class" }, { "bases": [], - "display_name": "ns1::ns2::R", + "display_name": "R", "id": "48082947340048353", "is_abstract": false, "is_nested": false, diff --git a/docs/test_cases/t00075_class.svg b/docs/test_cases/t00075_class.svg index 11628a5a..18b25506 100644 --- a/docs/test_cases/t00075_class.svg +++ b/docs/test_cases/t00075_class.svg @@ -1,6 +1,6 @@ - + @@ -9,14 +9,14 @@ - + ns1 - + ns2 - - + + @@ -30,8 +30,8 @@ T{} t.e() - - + + E @@ -40,40 +40,40 @@ k2 - - + + A - + - + e() const : E - - + + B - + - + e() const : E - - + + @@ -83,15 +83,15 @@ - + - + a_or_b : T - - + + @@ -101,8 +101,8 @@ - - + + @@ -112,8 +112,8 @@ - - + + @@ -121,18 +121,18 @@ - + - + a : ABE<A> - + - + b : ABE<B> diff --git a/docs/test_cases/t00075_class_mermaid.svg b/docs/test_cases/t00075_class_mermaid.svg index fbe488ac..4b89a13d 100644 --- a/docs/test_cases/t00075_class_mermaid.svg +++ b/docs/test_cases/t00075_class_mermaid.svg @@ -162,11 +162,11 @@ - + - +
@@ -183,20 +183,20 @@ "T{}"
- -
- "t.e()" -
-
- +
"(T t)"
+ +
+ "t.e() +
+
- + @@ -225,7 +225,7 @@ - + @@ -249,7 +249,7 @@ - + @@ -273,7 +273,7 @@ - + @@ -297,7 +297,7 @@ - + @@ -316,7 +316,7 @@ - + @@ -335,7 +335,7 @@ - + diff --git a/docs/test_cases/t20001.md b/docs/test_cases/t20001.md index ad8edfae..c2fd7462 100644 --- a/docs/test_cases/t20001.md +++ b/docs/test_cases/t20001.md @@ -120,6 +120,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20001::tmain()", "id": "622672604730036140", "name": "tmain", "namespace": "clanguml::t20001", @@ -135,6 +136,7 @@ int tmain() "activities": [ { "display_name": "A()", + "full_name": "clanguml::t20001::A::A()", "id": "275353461034438145", "name": "A", "namespace": "", @@ -148,6 +150,7 @@ int tmain() }, { "display_name": "add(int,int)", + "full_name": "clanguml::t20001::A::add(int,int)", "id": "1131549932713395402", "name": "add", "namespace": "", @@ -161,6 +164,7 @@ int tmain() }, { "display_name": "add3(int,int,int)", + "full_name": "clanguml::t20001::A::add3(int,int,int)", "id": "2090436635449419593", "name": "add3", "namespace": "", @@ -174,6 +178,7 @@ int tmain() }, { "display_name": "log_result(int)", + "full_name": "clanguml::t20001::A::log_result(int)", "id": "1205947631808952097", "name": "log_result", "namespace": "", @@ -187,6 +192,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20001::A", "id": "1771943546649183134", "name": "A", "namespace": "clanguml::t20001", @@ -202,6 +208,7 @@ int tmain() "activities": [ { "display_name": "B(A &)", + "full_name": "clanguml::t20001::B::B(A &)", "id": "2235477658795500000", "name": "B", "namespace": "", @@ -215,6 +222,7 @@ int tmain() }, { "display_name": "wrap_add3(int,int,int)", + "full_name": "clanguml::t20001::B::wrap_add3(int,int,int)", "id": "642550151323208936", "name": "wrap_add3", "namespace": "", @@ -228,6 +236,7 @@ int tmain() } ], "display_name": "B", + "full_name": "clanguml::t20001::B", "id": "272433898507800600", "name": "B", "namespace": "clanguml::t20001", diff --git a/docs/test_cases/t20001_sequence.svg b/docs/test_cases/t20001_sequence.svg index f102863b..3328d47a 100644 --- a/docs/test_cases/t20001_sequence.svg +++ b/docs/test_cases/t20001_sequence.svg @@ -1,6 +1,6 @@ - + @@ -10,79 +10,79 @@ Basic sequence diagram example - - - - - - - - - + + + + + + + + + - - + + tmain() - + tmain() - - + + A - + A - - + + B - + B - - - - - - - - - - + + + + + + + + + + A() - + B(A &) - + Just add 2 numbers - + add(int,int) - + And now add another 2 - + wrap_add3(int,int,int) - + add3(int,int,int) - + @@ -93,7 +93,7 @@ - + @@ -102,14 +102,14 @@ - + log_result(int) - + Main test function diff --git a/docs/test_cases/t20002.md b/docs/test_cases/t20002.md index 1c2908c0..481514d5 100644 --- a/docs/test_cases/t20002.md +++ b/docs/test_cases/t20002.md @@ -47,6 +47,7 @@ void m1() { m2(); } "participants": [ { "display_name": "m1()", + "full_name": "clanguml::t20002::m1()", "id": "1619421429271064154", "name": "m1", "namespace": "clanguml::t20002", @@ -60,6 +61,7 @@ void m1() { m2(); } }, { "display_name": "m2()", + "full_name": "clanguml::t20002::m2()", "id": "1575240232156112674", "name": "m2", "namespace": "clanguml::t20002", @@ -73,6 +75,7 @@ void m1() { m2(); } }, { "display_name": "m3()", + "full_name": "clanguml::t20002::m3()", "id": "1838809176089209580", "name": "m3", "namespace": "clanguml::t20002", @@ -86,6 +89,7 @@ void m1() { m2(); } }, { "display_name": "m4()", + "full_name": "clanguml::t20002::m4()", "id": "63715062711218534", "name": "m4", "namespace": "clanguml::t20002", diff --git a/docs/test_cases/t20002_sequence.svg b/docs/test_cases/t20002_sequence.svg index 05f44ae3..af825fa9 100644 --- a/docs/test_cases/t20002_sequence.svg +++ b/docs/test_cases/t20002_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,51 +9,51 @@ - - - - + + + + - - + + m1() - + m1() - - + + m2() - + m2() - - + + m3() - + m3() - - + + m4() - + m4() - - - - - + + + + + - + - + diff --git a/docs/test_cases/t20003.md b/docs/test_cases/t20003.md index a8383069..50382330 100644 --- a/docs/test_cases/t20003.md +++ b/docs/test_cases/t20003.md @@ -43,6 +43,7 @@ template void m1(T p) { m2(p); } "participants": [ { "display_name": "m1(T)", + "full_name": "clanguml::t20003::m1(T)", "id": "469205740799240869", "name": "m1", "namespace": "clanguml::t20003", @@ -56,6 +57,7 @@ template void m1(T p) { m2(p); } }, { "display_name": "m2(T)", + "full_name": "clanguml::t20003::m2(T)", "id": "1502957449367040488", "name": "m2", "namespace": "clanguml::t20003", @@ -69,6 +71,7 @@ template void m1(T p) { m2(p); } }, { "display_name": "m3(T)", + "full_name": "clanguml::t20003::m3(T)", "id": "613477682313507585", "name": "m3", "namespace": "clanguml::t20003", @@ -82,6 +85,7 @@ template void m1(T p) { m2(p); } }, { "display_name": "m4(T)", + "full_name": "clanguml::t20003::m4(T)", "id": "619960023608507925", "name": "m4", "namespace": "clanguml::t20003", diff --git a/docs/test_cases/t20003_sequence.svg b/docs/test_cases/t20003_sequence.svg index d82d7710..453055fc 100644 --- a/docs/test_cases/t20003_sequence.svg +++ b/docs/test_cases/t20003_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,51 +9,51 @@ - - - - + + + + - - + + m1<T>(T) - + m1<T>(T) - - + + m2<T>(T) - + m2<T>(T) - - + + m3<T>(T) - + m3<T>(T) - - + + m4<T>(T) - + m4<T>(T) - - - - - + + + + + - + - + diff --git a/docs/test_cases/t20004.md b/docs/test_cases/t20004.md index a8c5edd5..c9e2c49f 100644 --- a/docs/test_cases/t20004.md +++ b/docs/test_cases/t20004.md @@ -79,6 +79,7 @@ int main() "participants": [ { "display_name": "main()", + "full_name": "clanguml::t20004::main()", "id": "2299662004367884401", "name": "main", "namespace": "clanguml::t20004", @@ -92,6 +93,7 @@ int main() }, { "display_name": "m1(float)", + "full_name": "clanguml::t20004::m1(float)", "id": "138925040763435897", "name": "m1", "namespace": "clanguml::t20004", @@ -105,6 +107,7 @@ int main() }, { "display_name": "m1(unsigned long)", + "full_name": "clanguml::t20004::m1(unsigned long)", "id": "1239083518717603720", "name": "m1", "namespace": "clanguml::t20004", @@ -118,6 +121,7 @@ int main() }, { "display_name": "m4(unsigned long)", + "full_name": "clanguml::t20004::m4(unsigned long)", "id": "376599675205498367", "name": "m4", "namespace": "clanguml::t20004", @@ -131,6 +135,7 @@ int main() }, { "display_name": "m1(std::string)", + "full_name": "clanguml::t20004::m1(std::string)", "id": "1845817984839618223", "name": "m1", "namespace": "clanguml::t20004", @@ -144,6 +149,7 @@ int main() }, { "display_name": "m2(std::string)", + "full_name": "clanguml::t20004::m2(std::string)", "id": "1735054254122948614", "name": "m2", "namespace": "clanguml::t20004", @@ -157,6 +163,7 @@ int main() }, { "display_name": "m1(int)", + "full_name": "clanguml::t20004::m1(int)", "id": "121663532044911922", "name": "m1", "namespace": "clanguml::t20004", @@ -170,6 +177,7 @@ int main() }, { "display_name": "m2(int)", + "full_name": "clanguml::t20004::m2(int)", "id": "1475362124497386656", "name": "m2", "namespace": "clanguml::t20004", @@ -183,6 +191,7 @@ int main() }, { "display_name": "m3(int)", + "full_name": "clanguml::t20004::m3(int)", "id": "734999226157549914", "name": "m3", "namespace": "clanguml::t20004", @@ -196,6 +205,7 @@ int main() }, { "display_name": "m4(int)", + "full_name": "clanguml::t20004::m4(int)", "id": "1006390865908497562", "name": "m4", "namespace": "clanguml::t20004", diff --git a/docs/test_cases/t20004_sequence.svg b/docs/test_cases/t20004_sequence.svg index a510e441..576db1e0 100644 --- a/docs/test_cases/t20004_sequence.svg +++ b/docs/test_cases/t20004_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,16 +9,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -29,87 +29,87 @@ - - + + main() - + main() - - + + m1<float>(float) - + m1<float>(float) - - + + m1<unsigned long>(unsigned long) - + m1<unsigned long>(unsigned long) - - + + m4<unsigned long>(unsigned long) - + m4<unsigned long>(unsigned long) - - + + m1<std::string>(std::string) - + m1<std::string>(std::string) - - + + m2<std::string>(std::string) - + m2<std::string>(std::string) - - + + m1<int>(int) - + m1<int>(int) - - + + m2<int>(int) - + m2<int>(int) - - + + m3<int>(int) - + m3<int>(int) - - + + m4<int>(int) - + m4<int>(int) - - - - - - - - - - - + + + + + + + + + + + - + - + @@ -117,11 +117,11 @@ - + - + @@ -129,19 +129,19 @@ - + - + - + - + diff --git a/docs/test_cases/t20005.md b/docs/test_cases/t20005.md index daa14c5a..36feee57 100644 --- a/docs/test_cases/t20005.md +++ b/docs/test_cases/t20005.md @@ -52,6 +52,7 @@ template struct C { "activities": [ { "display_name": "c(T)", + "full_name": "clanguml::t20005::C::c(T)", "id": "578718872965404973", "name": "c", "namespace": "", @@ -65,6 +66,7 @@ template struct C { } ], "display_name": "C", + "full_name": "clanguml::t20005::C", "id": "365569130532127604", "name": "C", "namespace": "clanguml::t20005", @@ -80,6 +82,7 @@ template struct C { "activities": [ { "display_name": "b(T)", + "full_name": "clanguml::t20005::B::b(T)", "id": "870466496899932117", "name": "b", "namespace": "", @@ -93,6 +96,7 @@ template struct C { } ], "display_name": "B", + "full_name": "clanguml::t20005::B", "id": "666000829532846850", "name": "B", "namespace": "clanguml::t20005", @@ -108,6 +112,7 @@ template struct C { "activities": [ { "display_name": "a(T)", + "full_name": "clanguml::t20005::A::a(T)", "id": "124853455814403745", "name": "a", "namespace": "", @@ -121,6 +126,7 @@ template struct C { } ], "display_name": "A", + "full_name": "clanguml::t20005::A", "id": "1278330455625941185", "name": "A", "namespace": "clanguml::t20005", diff --git a/docs/test_cases/t20005_sequence.svg b/docs/test_cases/t20005_sequence.svg index 464aca3f..129fe281 100644 --- a/docs/test_cases/t20005_sequence.svg +++ b/docs/test_cases/t20005_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,42 +9,42 @@ - - - + + + - - + + C<T> - + C<T> - - + + B<T> - + B<T> - - + + A<T> - + A<T> - - - + + + c(T) - + b(T) - + a(T) diff --git a/docs/test_cases/t20006.md b/docs/test_cases/t20006.md index afb11868..59c28d0b 100644 --- a/docs/test_cases/t20006.md +++ b/docs/test_cases/t20006.md @@ -108,6 +108,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20006::tmain()", "id": "363965584448680958", "name": "tmain", "namespace": "clanguml::t20006", @@ -123,6 +124,7 @@ void tmain() "activities": [ { "display_name": "b(int)", + "full_name": "clanguml::t20006::B::b(int)", "id": "250247217888843587", "name": "b", "namespace": "", @@ -136,6 +138,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20006::B", "id": "2197760498261923035", "name": "B", "namespace": "clanguml::t20006", @@ -151,6 +154,7 @@ void tmain() "activities": [ { "display_name": "a1(int)", + "full_name": "clanguml::t20006::A::a1(int)", "id": "196390487987395669", "name": "a1", "namespace": "", @@ -164,6 +168,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20006::A", "id": "596484796124829039", "name": "A", "namespace": "clanguml::t20006", @@ -179,6 +184,7 @@ void tmain() "activities": [ { "display_name": "b(std::string)", + "full_name": "clanguml::t20006::B::b(std::string)", "id": "13049632552871157", "name": "b", "namespace": "", @@ -192,6 +198,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20006::B", "id": "2102622661983365981", "name": "B", "namespace": "clanguml::t20006", @@ -207,6 +214,7 @@ void tmain() "activities": [ { "display_name": "a2(std::string)", + "full_name": "clanguml::t20006::A::a2(std::string)", "id": "11762588624112907", "name": "a2", "namespace": "", @@ -220,6 +228,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20006::A", "id": "413459875415381273", "name": "A", "namespace": "clanguml::t20006", @@ -235,6 +244,7 @@ void tmain() "activities": [ { "display_name": "BB(AA *)", + "full_name": "clanguml::t20006::BB::BB(AA *)", "id": "381732876807761480", "name": "BB", "namespace": "", @@ -248,6 +258,7 @@ void tmain() }, { "display_name": "bb1(int,std::string)", + "full_name": "clanguml::t20006::BB::bb1(int,std::string)", "id": "1062874005712014125", "name": "bb1", "namespace": "", @@ -261,6 +272,7 @@ void tmain() }, { "display_name": "bb2(int,std::string)", + "full_name": "clanguml::t20006::BB::bb2(int,std::string)", "id": "787705189994778234", "name": "bb2", "namespace": "", @@ -274,6 +286,7 @@ void tmain() } ], "display_name": "BB", + "full_name": "clanguml::t20006::BB", "id": "2269742833301555472", "name": "BB", "namespace": "clanguml::t20006", @@ -289,6 +302,7 @@ void tmain() "activities": [ { "display_name": "BB(AA &)", + "full_name": "clanguml::t20006::BB::BB(AA &)", "id": "1051013203072323842", "name": "BB", "namespace": "", @@ -302,6 +316,7 @@ void tmain() }, { "display_name": "bb1(int,float)", + "full_name": "clanguml::t20006::BB::bb1(int,float)", "id": "1463188845572485713", "name": "bb1", "namespace": "", @@ -315,6 +330,7 @@ void tmain() }, { "display_name": "bb2(int,float)", + "full_name": "clanguml::t20006::BB::bb2(int,float)", "id": "732362671329401903", "name": "bb2", "namespace": "", @@ -328,6 +344,7 @@ void tmain() } ], "display_name": "BB", + "full_name": "clanguml::t20006::BB", "id": "1743503037360505162", "name": "BB", "namespace": "clanguml::t20006", @@ -343,6 +360,7 @@ void tmain() "activities": [ { "display_name": "bb1(int,int)", + "full_name": "clanguml::t20006::BB::bb1(int,int)", "id": "1213865121829347654", "name": "bb1", "namespace": "", @@ -356,6 +374,7 @@ void tmain() }, { "display_name": "bb2(int,int)", + "full_name": "clanguml::t20006::BB::bb2(int,int)", "id": "361650123916792854", "name": "bb2", "namespace": "", @@ -369,6 +388,7 @@ void tmain() } ], "display_name": "BB", + "full_name": "clanguml::t20006::BB", "id": "264392653889863384", "name": "BB", "namespace": "clanguml::t20006", @@ -384,6 +404,7 @@ void tmain() "activities": [ { "display_name": "aa1(int)", + "full_name": "clanguml::t20006::AA::aa1(int)", "id": "1235428163990670191", "name": "aa1", "namespace": "", @@ -397,6 +418,7 @@ void tmain() }, { "display_name": "aa2(int)", + "full_name": "clanguml::t20006::AA::aa2(int)", "id": "582097827335267290", "name": "aa2", "namespace": "", @@ -410,6 +432,7 @@ void tmain() } ], "display_name": "AA", + "full_name": "clanguml::t20006::AA", "id": "1903567228894636312", "name": "AA", "namespace": "clanguml::t20006", @@ -491,7 +514,7 @@ void tmain() "participant_id": "2102622661983365981" }, "name": "a2(std::string)", - "return_type": "std::basic_string", + "return_type": "std::string", "scope": "normal", "source_location": { "column": 45, diff --git a/docs/test_cases/t20006_sequence.svg b/docs/test_cases/t20006_sequence.svg index 0acd1a86..cddbc271 100644 --- a/docs/test_cases/t20006_sequence.svg +++ b/docs/test_cases/t20006_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,24 +9,24 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -36,84 +36,84 @@ - - + + tmain() - + tmain() - - + + B<int> - + B<int> - - + + A<int> - + A<int> - - + + B<std::string> - + B<std::string> - - + + A<std::string> - + A<std::string> - - + + BB<int,std::string> - + BB<int,std::string> - - + + BB<int,float> - + BB<int,float> - - + + BB<int,int> - + BB<int,int> - - + + AA<int> - + AA<int> - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + b(int) - + a1(int) @@ -122,12 +122,12 @@ - + b(std::string) - + a2(std::string) @@ -136,69 +136,69 @@ - + BB(AA<int> *) - + BB(AA<int> &) - + bb1(int,int) - + aa1(int) - + bb2(int,int) - + aa2(int) - + bb1(int,std::string) - + aa2(int) - + bb2(int,std::string) - + aa1(int) - + bb1(int,float) - + bb2(int,float) - + aa2(int) diff --git a/docs/test_cases/t20007.md b/docs/test_cases/t20007.md index 8b727497..31bd73c9 100644 --- a/docs/test_cases/t20007.md +++ b/docs/test_cases/t20007.md @@ -54,6 +54,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20007::tmain()", "id": "622662006747239840", "name": "tmain", "namespace": "clanguml::t20007", @@ -69,6 +70,7 @@ void tmain() "activities": [ { "display_name": "add(int &&,int &&)", + "full_name": "clanguml::t20007::Adder::add(int &&,int &&)", "id": "438133719207269065", "name": "add", "namespace": "", @@ -82,6 +84,7 @@ void tmain() } ], "display_name": "Adder", + "full_name": "clanguml::t20007::Adder", "id": "1742497005509009302", "name": "Adder", "namespace": "clanguml::t20007", @@ -97,6 +100,7 @@ void tmain() "activities": [ { "display_name": "add(int &&,float &&,double &&)", + "full_name": "clanguml::t20007::Adder::add(int &&,float &&,double &&)", "id": "9522724767688870", "name": "add", "namespace": "", @@ -110,6 +114,7 @@ void tmain() } ], "display_name": "Adder", + "full_name": "clanguml::t20007::Adder", "id": "599640474306956868", "name": "Adder", "namespace": "clanguml::t20007", @@ -125,6 +130,7 @@ void tmain() "activities": [ { "display_name": "add(std::string &&,std::string &&,std::string &&)", + "full_name": "clanguml::t20007::Adder::add(std::string &&,std::string &&,std::string &&)", "id": "384866641042941480", "name": "add", "namespace": "", @@ -138,6 +144,7 @@ void tmain() } ], "display_name": "Adder", + "full_name": "clanguml::t20007::Adder", "id": "228191787514523926", "name": "Adder", "namespace": "clanguml::t20007", @@ -199,7 +206,7 @@ void tmain() "participant_id": "622662006747239840" }, "name": "add(std::string &&,std::string &&,std::string &&)", - "return_type": "std::basic_string", + "return_type": "std::string", "scope": "normal", "source_location": { "column": 34, diff --git a/docs/test_cases/t20007_sequence.svg b/docs/test_cases/t20007_sequence.svg index bcc295e6..c0528cb1 100644 --- a/docs/test_cases/t20007_sequence.svg +++ b/docs/test_cases/t20007_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,57 +9,57 @@ - - - - + + + + - - + + tmain() - + tmain() - - + + Adder<int,int> - + Adder<int,int> - - + + Adder<int,float,double> - + Adder<int,float,double> - - + + Adder<std::string,std::string,std::string> - + Adder<std::string,std::string,std::string> - - - - - + + + + + add(int &&,int &&) - + add(int &&,float &&,double &&) - + add(std::string &&,std::string &&,std::string &&) diff --git a/docs/test_cases/t20008.md b/docs/test_cases/t20008.md index 7db49a43..76969d1d 100644 --- a/docs/test_cases/t20008.md +++ b/docs/test_cases/t20008.md @@ -72,6 +72,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20008::tmain()", "id": "1180776240543224244", "name": "tmain", "namespace": "clanguml::t20008", @@ -87,6 +88,7 @@ void tmain() "activities": [ { "display_name": "b(int)", + "full_name": "clanguml::t20008::B::b(int)", "id": "379850145437051189", "name": "b", "namespace": "", @@ -100,6 +102,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20008::B", "id": "1906510289157013670", "name": "B", "namespace": "clanguml::t20008", @@ -115,6 +118,7 @@ void tmain() "activities": [ { "display_name": "a1(int)", + "full_name": "clanguml::t20008::A::a1(int)", "id": "2066363630174644719", "name": "a1", "namespace": "", @@ -128,6 +132,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20008::A", "id": "1376149084762923197", "name": "A", "namespace": "clanguml::t20008", @@ -143,6 +148,7 @@ void tmain() "activities": [ { "display_name": "b(const char *)", + "full_name": "clanguml::t20008::B::b(const char *)", "id": "1347162523481637780", "name": "b", "namespace": "", @@ -156,6 +162,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20008::B", "id": "867098551202196741", "name": "B", "namespace": "clanguml::t20008", @@ -171,6 +178,7 @@ void tmain() "activities": [ { "display_name": "a2(const char *)", + "full_name": "clanguml::t20008::A::a2(const char *)", "id": "718650834962275580", "name": "a2", "namespace": "", @@ -184,6 +192,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20008::A", "id": "144833378017373200", "name": "A", "namespace": "clanguml::t20008", @@ -199,6 +208,7 @@ void tmain() "activities": [ { "display_name": "b(std::string)", + "full_name": "clanguml::t20008::B::b(std::string)", "id": "1286410946666951254", "name": "b", "namespace": "", @@ -212,6 +222,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20008::B", "id": "927702553742507923", "name": "B", "namespace": "clanguml::t20008", @@ -227,6 +238,7 @@ void tmain() "activities": [ { "display_name": "a3(std::string)", + "full_name": "clanguml::t20008::A::a3(std::string)", "id": "1404594247101138737", "name": "a3", "namespace": "", @@ -240,6 +252,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20008::A", "id": "390605614583363778", "name": "A", "namespace": "clanguml::t20008", diff --git a/docs/test_cases/t20008_sequence.svg b/docs/test_cases/t20008_sequence.svg index eb332ea9..2f9237ba 100644 --- a/docs/test_cases/t20008_sequence.svg +++ b/docs/test_cases/t20008_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,13 +9,13 @@ - - - - - - - + + + + + + + @@ -23,81 +23,81 @@ - - + + tmain() - + tmain() - - + + B<int> - + B<int> - - + + A<int> - + A<int> - - + + B<const char *> - + B<const char *> - - + + A<const char *> - + A<const char *> - - + + B<std::string> - + B<std::string> - - + + A<std::string> - + A<std::string> - - - - - - - - + + + + + + + + b(int) - + a1(int) - + b(const char *) - + a2(const char *) - + b(std::string) - + a3(std::string) diff --git a/docs/test_cases/t20009.md b/docs/test_cases/t20009.md index 4df3f8d4..664a6e17 100644 --- a/docs/test_cases/t20009.md +++ b/docs/test_cases/t20009.md @@ -58,6 +58,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20009::tmain()", "id": "791066686606379857", "name": "tmain", "namespace": "clanguml::t20009", @@ -73,6 +74,7 @@ void tmain() "activities": [ { "display_name": "b(std::string)", + "full_name": "clanguml::t20009::B::b(std::string)", "id": "1960266381909090879", "name": "b", "namespace": "", @@ -86,6 +88,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20009::B", "id": "450813573860627679", "name": "B", "namespace": "clanguml::t20009", @@ -101,6 +104,7 @@ void tmain() "activities": [ { "display_name": "a(std::string)", + "full_name": "clanguml::t20009::A::a(std::string)", "id": "1716775846967761286", "name": "a", "namespace": "", @@ -114,6 +118,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20009::A", "id": "1197403810800583218", "name": "A", "namespace": "clanguml::t20009", @@ -129,6 +134,7 @@ void tmain() "activities": [ { "display_name": "b(int)", + "full_name": "clanguml::t20009::B::b(int)", "id": "660557928399203634", "name": "b", "namespace": "", @@ -142,6 +148,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20009::B", "id": "2002310682025149090", "name": "B", "namespace": "clanguml::t20009", @@ -157,6 +164,7 @@ void tmain() "activities": [ { "display_name": "a(int)", + "full_name": "clanguml::t20009::A::a(int)", "id": "2030629454810805092", "name": "a", "namespace": "", @@ -170,6 +178,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20009::A", "id": "1228498754558363121", "name": "A", "namespace": "clanguml::t20009", @@ -185,6 +194,7 @@ void tmain() "activities": [ { "display_name": "b(float)", + "full_name": "clanguml::t20009::B::b(float)", "id": "367805163135583282", "name": "b", "namespace": "", @@ -198,6 +208,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20009::B", "id": "1461902328659683203", "name": "B", "namespace": "clanguml::t20009", @@ -213,6 +224,7 @@ void tmain() "activities": [ { "display_name": "a(float)", + "full_name": "clanguml::t20009::A::a(float)", "id": "1643733911490581293", "name": "a", "namespace": "", @@ -226,6 +238,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20009::A", "id": "1243520246309441967", "name": "A", "namespace": "clanguml::t20009", diff --git a/docs/test_cases/t20009_sequence.svg b/docs/test_cases/t20009_sequence.svg index 7e7c4dde..a7dc00b8 100644 --- a/docs/test_cases/t20009_sequence.svg +++ b/docs/test_cases/t20009_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,13 +9,13 @@ - - - - - - - + + + + + + + @@ -23,81 +23,81 @@ - - + + tmain() - + tmain() - - + + B<std::string> - + B<std::string> - - + + A<std::string> - + A<std::string> - - + + B<int> - + B<int> - - + + A<int> - + A<int> - - + + B<float> - + B<float> - - + + A<float> - + A<float> - - - - - - - - + + + + + + + + b(std::string) - + a(std::string) - + b(int) - + a(int) - + b(float) - + a(float) diff --git a/docs/test_cases/t20010.md b/docs/test_cases/t20010.md index 56336dc4..600e5f34 100644 --- a/docs/test_cases/t20010.md +++ b/docs/test_cases/t20010.md @@ -68,6 +68,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20010::tmain()", "id": "1364660609791735244", "name": "tmain", "namespace": "clanguml::t20010", @@ -83,6 +84,7 @@ void tmain() "activities": [ { "display_name": "b1()", + "full_name": "clanguml::t20010::B::b1()", "id": "343626060927491836", "name": "b1", "namespace": "", @@ -96,6 +98,7 @@ void tmain() }, { "display_name": "b2()", + "full_name": "clanguml::t20010::B::b2()", "id": "1633031113603062043", "name": "b2", "namespace": "", @@ -109,6 +112,7 @@ void tmain() }, { "display_name": "b3()", + "full_name": "clanguml::t20010::B::b3()", "id": "786218543654309692", "name": "b3", "namespace": "", @@ -122,6 +126,7 @@ void tmain() }, { "display_name": "b4()", + "full_name": "clanguml::t20010::B::b4()", "id": "1866068965397702666", "name": "b4", "namespace": "", @@ -135,6 +140,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20010::B", "id": "2154977200904210115", "name": "B", "namespace": "clanguml::t20010", @@ -150,6 +156,7 @@ void tmain() "activities": [ { "display_name": "a1()", + "full_name": "clanguml::t20010::A::a1()", "id": "981184681827469850", "name": "a1", "namespace": "", @@ -163,6 +170,7 @@ void tmain() }, { "display_name": "a2()", + "full_name": "clanguml::t20010::A::a2()", "id": "664370880632146592", "name": "a2", "namespace": "", @@ -176,6 +184,7 @@ void tmain() }, { "display_name": "a3()", + "full_name": "clanguml::t20010::A::a3()", "id": "2145739294823015899", "name": "a3", "namespace": "", @@ -189,6 +198,7 @@ void tmain() }, { "display_name": "a4()", + "full_name": "clanguml::t20010::A::a4()", "id": "1224936485834400821", "name": "a4", "namespace": "", @@ -202,6 +212,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20010::A", "id": "102070351492425113", "name": "A", "namespace": "clanguml::t20010", diff --git a/docs/test_cases/t20010_sequence.svg b/docs/test_cases/t20010_sequence.svg index 2a8946d7..5a00a566 100644 --- a/docs/test_cases/t20010_sequence.svg +++ b/docs/test_cases/t20010_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,81 +9,81 @@ - - - - - - - - - + + + + + + + + + - - + + tmain() - + tmain() - - + + B<int> - + B<int> - - + + A - + A - - - - - - - - - - + + + + + + + + + + b1() - + a1() - + b2() - + a2() - + b3() - + a3() - + b4() - + a4() diff --git a/docs/test_cases/t20011.md b/docs/test_cases/t20011.md index 9fa3443a..e0c1db8a 100644 --- a/docs/test_cases/t20011.md +++ b/docs/test_cases/t20011.md @@ -60,6 +60,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20011::tmain()", "id": "1866210527166391126", "name": "tmain", "namespace": "clanguml::t20011", @@ -75,6 +76,7 @@ void tmain() "activities": [ { "display_name": "a(int)", + "full_name": "clanguml::t20011::A::a(int)", "id": "1647578261840204206", "name": "a", "namespace": "", @@ -88,6 +90,7 @@ void tmain() }, { "display_name": "b(int)", + "full_name": "clanguml::t20011::A::b(int)", "id": "305456175818875420", "name": "b", "namespace": "", @@ -101,6 +104,7 @@ void tmain() }, { "display_name": "c(int)", + "full_name": "clanguml::t20011::A::c(int)", "id": "963268672079901211", "name": "c", "namespace": "", @@ -114,6 +118,7 @@ void tmain() }, { "display_name": "d(int)", + "full_name": "clanguml::t20011::A::d(int)", "id": "1874311762268001137", "name": "d", "namespace": "", @@ -127,6 +132,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20011::A", "id": "816061502062128285", "name": "A", "namespace": "clanguml::t20011", @@ -298,6 +304,38 @@ void tmain() "participant_id": "816061502062128285" }, "type": "message" + }, + { + "activity_id": "1647578261840204206", + "branches": [ + { + "messages": [ + { + "from": { + "activity_id": "1647578261840204206", + "participant_id": "816061502062128285" + }, + "name": "a(int)", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 13, + "file": "t20011.cc", + "line": 8, + "translation_unit": "t20011.cc" + }, + "to": { + "activity_id": "1647578261840204206", + "participant_id": "816061502062128285" + }, + "type": "message" + } + ], + "type": "consequent" + } + ], + "name": "if", + "type": "alt" } ], "type": "consequent" diff --git a/docs/test_cases/t20011_sequence.svg b/docs/test_cases/t20011_sequence.svg index cc031630..5e87647f 100644 --- a/docs/test_cases/t20011_sequence.svg +++ b/docs/test_cases/t20011_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,42 +9,42 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - + + tmain() - + tmain() - - + + A - + A - - - - - - - - - - + + + + + + + + + + a(int) @@ -52,26 +52,26 @@ alt - + a(int) - + b(int) - + c(int) - + @@ -81,14 +81,14 @@ alt - + b(int) - + @@ -98,7 +98,7 @@ alt - + diff --git a/docs/test_cases/t20012.md b/docs/test_cases/t20012.md index d00a8239..6eb66e0d 100644 --- a/docs/test_cases/t20012.md +++ b/docs/test_cases/t20012.md @@ -135,6 +135,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20012::tmain()", "id": "893699278278125827", "name": "tmain", "namespace": "clanguml::t20012", @@ -150,6 +151,7 @@ void tmain() "activities": [ { "display_name": "operator()() const", + "full_name": "clanguml::t20012::tmain()::(lambda t20012.cc:67:20)::operator()() const", "id": "844942554717397525", "name": "operator()", "namespace": "", @@ -157,6 +159,7 @@ void tmain() } ], "display_name": "tmain()::(lambda t20012.cc:67:20)", + "full_name": "clanguml::t20012::tmain()::(lambda t20012.cc:67:20)", "id": "1823127147500894672", "name": "tmain()::(lambda t20012.cc:67:20)", "namespace": "clanguml::t20012", @@ -172,6 +175,7 @@ void tmain() "activities": [ { "display_name": "a()", + "full_name": "clanguml::t20012::A::a()", "id": "1871432932744498976", "name": "a", "namespace": "", @@ -185,6 +189,7 @@ void tmain() }, { "display_name": "aa()", + "full_name": "clanguml::t20012::A::aa()", "id": "1100933039353876539", "name": "aa", "namespace": "", @@ -198,6 +203,7 @@ void tmain() }, { "display_name": "aaa()", + "full_name": "clanguml::t20012::A::aaa()", "id": "941636185823691898", "name": "aaa", "namespace": "", @@ -211,6 +217,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20012::A", "id": "1798184226128732119", "name": "A", "namespace": "clanguml::t20012", @@ -226,6 +233,7 @@ void tmain() "activities": [ { "display_name": "b()", + "full_name": "clanguml::t20012::B::b()", "id": "2142697410385270633", "name": "b", "namespace": "", @@ -239,6 +247,7 @@ void tmain() }, { "display_name": "bb()", + "full_name": "clanguml::t20012::B::bb()", "id": "973718340784931313", "name": "bb", "namespace": "", @@ -252,6 +261,7 @@ void tmain() }, { "display_name": "bbb()", + "full_name": "clanguml::t20012::B::bbb()", "id": "195788529004378403", "name": "bbb", "namespace": "", @@ -265,6 +275,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20012::B", "id": "1893469899260202653", "name": "B", "namespace": "clanguml::t20012", @@ -280,6 +291,7 @@ void tmain() "activities": [ { "display_name": "operator()() const", + "full_name": "clanguml::t20012::tmain()::(lambda t20012.cc:80:20)::operator()() const", "id": "2080867854705352490", "name": "operator()", "namespace": "", @@ -287,6 +299,7 @@ void tmain() } ], "display_name": "tmain()::(lambda t20012.cc:80:20)", + "full_name": "clanguml::t20012::tmain()::(lambda t20012.cc:80:20)", "id": "2103332104162021186", "name": "tmain()::(lambda t20012.cc:80:20)", "namespace": "clanguml::t20012", @@ -302,6 +315,7 @@ void tmain() "activities": [ { "display_name": "c()", + "full_name": "clanguml::t20012::C::c()", "id": "675369415318225607", "name": "c", "namespace": "", @@ -315,6 +329,7 @@ void tmain() }, { "display_name": "cc()", + "full_name": "clanguml::t20012::C::cc()", "id": "1451821704315336057", "name": "cc", "namespace": "", @@ -328,6 +343,7 @@ void tmain() }, { "display_name": "ccc()", + "full_name": "clanguml::t20012::C::ccc()", "id": "1956141408799600460", "name": "ccc", "namespace": "", @@ -341,6 +357,7 @@ void tmain() } ], "display_name": "C", + "full_name": "clanguml::t20012::C", "id": "2071958121786360262", "name": "C", "namespace": "clanguml::t20012", @@ -356,6 +373,7 @@ void tmain() "activities": [ { "display_name": "R((lambda at t20012.cc:86:9) &&)", + "full_name": "clanguml::t20012::R<(lambda at t20012.cc:86:9)>::R((lambda at t20012.cc:86:9) &&)", "id": "1976182450987832927", "name": "R", "namespace": "", @@ -369,6 +387,7 @@ void tmain() }, { "display_name": "r()", + "full_name": "clanguml::t20012::R<(lambda at t20012.cc:86:9)>::r()", "id": "1627963942447215983", "name": "r", "namespace": "", @@ -382,6 +401,7 @@ void tmain() } ], "display_name": "R<(lambda at t20012.cc:86:9)>", + "full_name": "clanguml::t20012::R<(lambda at t20012.cc:86:9)>", "id": "1418878159628415236", "name": "R", "namespace": "clanguml::t20012", @@ -397,6 +417,7 @@ void tmain() "activities": [ { "display_name": "operator()() const", + "full_name": "clanguml::t20012::tmain()::(lambda t20012.cc:86:9)::operator()() const", "id": "997617437879117371", "name": "operator()", "namespace": "", @@ -404,6 +425,7 @@ void tmain() } ], "display_name": "tmain()::(lambda t20012.cc:86:9)", + "full_name": "clanguml::t20012::tmain()::(lambda t20012.cc:86:9)", "id": "1523229682883773614", "name": "tmain()::(lambda t20012.cc:86:9)", "namespace": "clanguml::t20012", @@ -419,6 +441,7 @@ void tmain() "activities": [ { "display_name": "operator()(auto) const", + "full_name": "clanguml::t20012::tmain()::(lambda t20012.cc:94:9)::operator()(auto) const", "id": "1625806587339243213", "name": "operator()", "namespace": "", @@ -426,6 +449,7 @@ void tmain() } ], "display_name": "tmain()::(lambda t20012.cc:94:9)", + "full_name": "clanguml::t20012::tmain()::(lambda t20012.cc:94:9)", "id": "1585686021763298522", "name": "tmain()::(lambda t20012.cc:94:9)", "namespace": "clanguml::t20012", @@ -441,6 +465,7 @@ void tmain() "activities": [ { "display_name": "add5(int) const", + "full_name": "clanguml::t20012::D::add5(int) const", "id": "379068559069876883", "name": "add5", "namespace": "", @@ -454,6 +479,7 @@ void tmain() } ], "display_name": "D", + "full_name": "clanguml::t20012::D", "id": "1627226326147373737", "name": "D", "namespace": "clanguml::t20012", @@ -709,6 +735,126 @@ void tmain() }, "type": "message" }, + { + "from": { + "activity_id": "844942554717397525", + "participant_id": "1823127147500894672" + }, + "name": "a()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 9, + "file": "t20012.cc", + "line": 68, + "translation_unit": "t20012.cc" + }, + "to": { + "activity_id": "1871432932744498976", + "participant_id": "1798184226128732119" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1871432932744498976", + "participant_id": "1798184226128732119" + }, + "name": "aa()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 16, + "file": "t20012.cc", + "line": 11, + "translation_unit": "t20012.cc" + }, + "to": { + "activity_id": "1100933039353876539", + "participant_id": "1798184226128732119" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1100933039353876539", + "participant_id": "1798184226128732119" + }, + "name": "aaa()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 17, + "file": "t20012.cc", + "line": 13, + "translation_unit": "t20012.cc" + }, + "to": { + "activity_id": "941636185823691898", + "participant_id": "1798184226128732119" + }, + "type": "message" + }, + { + "from": { + "activity_id": "844942554717397525", + "participant_id": "1823127147500894672" + }, + "name": "b()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 9, + "file": "t20012.cc", + "line": 69, + "translation_unit": "t20012.cc" + }, + "to": { + "activity_id": "2142697410385270633", + "participant_id": "1893469899260202653" + }, + "type": "message" + }, + { + "from": { + "activity_id": "2142697410385270633", + "participant_id": "1893469899260202653" + }, + "name": "bb()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 16, + "file": "t20012.cc", + "line": 19, + "translation_unit": "t20012.cc" + }, + "to": { + "activity_id": "973718340784931313", + "participant_id": "1893469899260202653" + }, + "type": "message" + }, + { + "from": { + "activity_id": "973718340784931313", + "participant_id": "1893469899260202653" + }, + "name": "bbb()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 17, + "file": "t20012.cc", + "line": 21, + "translation_unit": "t20012.cc" + }, + "to": { + "activity_id": "195788529004378403", + "participant_id": "1893469899260202653" + }, + "type": "message" + }, { "from": { "activity_id": "893699278278125827", @@ -789,6 +935,46 @@ void tmain() }, "type": "message" }, + { + "from": { + "activity_id": "675369415318225607", + "participant_id": "2071958121786360262" + }, + "name": "cc()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 16, + "file": "t20012.cc", + "line": 29, + "translation_unit": "t20012.cc" + }, + "to": { + "activity_id": "1451821704315336057", + "participant_id": "2071958121786360262" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1451821704315336057", + "participant_id": "2071958121786360262" + }, + "name": "ccc()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 17, + "file": "t20012.cc", + "line": 31, + "translation_unit": "t20012.cc" + }, + "to": { + "activity_id": "1956141408799600460", + "participant_id": "2071958121786360262" + }, + "type": "message" + }, { "from": { "activity_id": "893699278278125827", diff --git a/docs/test_cases/t20012_sequence.svg b/docs/test_cases/t20012_sequence.svg index 6f479003..e1828115 100644 --- a/docs/test_cases/t20012_sequence.svg +++ b/docs/test_cases/t20012_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,33 +9,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -46,243 +46,243 @@ - - + + tmain() - + tmain() - - + + tmain()::(lambda t20012.cc:67:20) - + tmain()::(lambda t20012.cc:67:20) - - + + A - + A - - + + B - + B - - + + tmain()::(lambda t20012.cc:80:20) - + tmain()::(lambda t20012.cc:80:20) - - + + C - + C - - + + R<(lambda at t20012.cc:86:9)> - + R<(lambda at t20012.cc:86:9)> - - + + tmain()::(lambda t20012.cc:86:9) - + tmain()::(lambda t20012.cc:86:9) - - + + tmain()::(lambda t20012.cc:94:9) - + tmain()::(lambda t20012.cc:94:9) - - + + D - + D - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + operator()() const - + a() - + aa() - + aaa() - + b() - + bb() - + bbb() - + operator()() const - + c() - + cc() - + ccc() - + operator()() const - + a() - + aa() - + aaa() - + b() - + bb() - + bbb() - + R((lambda at t20012.cc:86:9) &&) - + r() - + operator()() const - + c() - + cc() - + ccc() - + operator()(auto) const - + add5(int) const diff --git a/docs/test_cases/t20013.md b/docs/test_cases/t20013.md index 98eef980..261586f4 100644 --- a/docs/test_cases/t20013.md +++ b/docs/test_cases/t20013.md @@ -56,6 +56,7 @@ void tmain(int argc, char **argv) "participants": [ { "display_name": "tmain(int,char **)", + "full_name": "clanguml::t20013::tmain(int,char **)", "id": "1249768632077843821", "name": "tmain", "namespace": "clanguml::t20013", @@ -71,6 +72,7 @@ void tmain(int argc, char **argv) "activities": [ { "display_name": "b(int)", + "full_name": "clanguml::t20013::B::b(int)", "id": "2144804108273682993", "name": "b", "namespace": "", @@ -84,6 +86,7 @@ void tmain(int argc, char **argv) }, { "display_name": "b(double)", + "full_name": "clanguml::t20013::B::b(double)", "id": "640747884486165287", "name": "b", "namespace": "", @@ -97,6 +100,7 @@ void tmain(int argc, char **argv) }, { "display_name": "b(const char *)", + "full_name": "clanguml::t20013::B::b(const char *)", "id": "1066935874364409142", "name": "b", "namespace": "", @@ -110,6 +114,7 @@ void tmain(int argc, char **argv) } ], "display_name": "B", + "full_name": "clanguml::t20013::B", "id": "1106407610612951303", "name": "B", "namespace": "clanguml::t20013", @@ -125,6 +130,7 @@ void tmain(int argc, char **argv) "activities": [ { "display_name": "a1(int)", + "full_name": "clanguml::t20013::A::a1(int)", "id": "1034027282942033004", "name": "a1", "namespace": "", @@ -138,6 +144,7 @@ void tmain(int argc, char **argv) }, { "display_name": "a2(double)", + "full_name": "clanguml::t20013::A::a2(double)", "id": "394053399890813915", "name": "a2", "namespace": "", @@ -151,6 +158,7 @@ void tmain(int argc, char **argv) }, { "display_name": "a3(const char *)", + "full_name": "clanguml::t20013::A::a3(const char *)", "id": "1841239321495867611", "name": "a3", "namespace": "", @@ -164,6 +172,7 @@ void tmain(int argc, char **argv) } ], "display_name": "A", + "full_name": "clanguml::t20013::A", "id": "976623130699225079", "name": "A", "namespace": "clanguml::t20013", diff --git a/docs/test_cases/t20013_sequence.svg b/docs/test_cases/t20013_sequence.svg index b3bca1da..045dd983 100644 --- a/docs/test_cases/t20013_sequence.svg +++ b/docs/test_cases/t20013_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,47 +9,47 @@ - - - - - - - + + + + + + + - - + + tmain(int,char **) - + tmain(int,char **) - - + + B - + B - - + + A - + A - - - - - - - - + + + + + + + + b(int) - + a1(int) @@ -58,12 +58,12 @@ - + b(double) - + a2(double) @@ -72,12 +72,12 @@ - + b(const char *) - + a3(const char *) diff --git a/docs/test_cases/t20014.md b/docs/test_cases/t20014.md index 59d155bd..d389364a 100644 --- a/docs/test_cases/t20014.md +++ b/docs/test_cases/t20014.md @@ -155,6 +155,7 @@ struct A { "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20014::tmain()", "id": "512436830818921250", "name": "tmain", "namespace": "clanguml::t20014", @@ -170,6 +171,7 @@ struct A { "activities": [ { "display_name": "b1(int,int)", + "full_name": "clanguml::t20014::B::b1(int,int)", "id": "1251633571711578431", "name": "b1", "namespace": "", @@ -183,6 +185,7 @@ struct A { }, { "display_name": "b2(int,int)", + "full_name": "clanguml::t20014::B::b2(int,int)", "id": "767830966714379991", "name": "b2", "namespace": "", @@ -196,6 +199,7 @@ struct A { } ], "display_name": "B", + "full_name": "clanguml::t20014::B", "id": "1537634076295867978", "name": "B", "namespace": "clanguml::t20014", @@ -211,6 +215,7 @@ struct A { "activities": [ { "display_name": "a1(int,int)", + "full_name": "clanguml::t20014::A::a1(int,int)", "id": "1753682948110709616", "name": "a1", "namespace": "", @@ -224,6 +229,7 @@ struct A { }, { "display_name": "a2(int,int)", + "full_name": "clanguml::t20014::A::a2(int,int)", "id": "1943487088673912694", "name": "a2", "namespace": "", @@ -237,6 +243,7 @@ struct A { } ], "display_name": "A", + "full_name": "clanguml::t20014::A", "id": "1504706415756333840", "name": "A", "namespace": "clanguml::t20014", @@ -252,6 +259,7 @@ struct A { "activities": [ { "display_name": "c1(int,int)", + "full_name": "clanguml::t20014::C::c1(int,int)", "id": "407559038402563981", "name": "c1", "namespace": "", @@ -265,6 +273,7 @@ struct A { } ], "display_name": "C", + "full_name": "clanguml::t20014::C", "id": "500712304857049435", "name": "C", "namespace": "clanguml::t20014", @@ -399,6 +408,26 @@ struct A { "participant_id": "1537634076295867978" }, "type": "message" + }, + { + "from": { + "activity_id": "1251633571711578431", + "participant_id": "1537634076295867978" + }, + "name": "a1(int,int)", + "return_type": "int", + "scope": "normal", + "source_location": { + "column": 34, + "file": "t20014_b.cc", + "line": 5, + "translation_unit": "t20014_b.cc" + }, + "to": { + "activity_id": "1753682948110709616", + "participant_id": "1504706415756333840" + }, + "type": "message" } ], "start_from": { diff --git a/docs/test_cases/t20014_sequence.svg b/docs/test_cases/t20014_sequence.svg index 559ac2ea..91f4294a 100644 --- a/docs/test_cases/t20014_sequence.svg +++ b/docs/test_cases/t20014_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,56 +9,56 @@ - - - - - - - - + + + + + + + + - - + + tmain() - + tmain() - - + + B - + B - - + + A - + A - - + + C<B,int> - + C<B,int> - - - - - - - - - + + + + + + + + + b1(int,int) - + a1(int,int) @@ -67,12 +67,12 @@ - + b2(int,int) - + a2(int,int) @@ -81,17 +81,17 @@ - + c1(int,int) - + b1(int,int) - + a1(int,int) diff --git a/docs/test_cases/t20015.md b/docs/test_cases/t20015.md index 3cd38edd..65d268b0 100644 --- a/docs/test_cases/t20015.md +++ b/docs/test_cases/t20015.md @@ -72,6 +72,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20015::tmain()", "id": "1011496551872082945", "name": "tmain", "namespace": "clanguml::t20015", @@ -87,6 +88,7 @@ void tmain() "activities": [ { "display_name": "setup_a(std::shared_ptr &)", + "full_name": "clanguml::t20015::B::setup_a(std::shared_ptr &)", "id": "431575772398797060", "name": "setup_a", "namespace": "", @@ -100,6 +102,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20015::B", "id": "1302656676783358645", "name": "B", "namespace": "clanguml::t20015", diff --git a/docs/test_cases/t20015_sequence.svg b/docs/test_cases/t20015_sequence.svg index dd49de9a..ab2bc1a6 100644 --- a/docs/test_cases/t20015_sequence.svg +++ b/docs/test_cases/t20015_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,25 +9,25 @@ - - + + - - + + tmain() - + tmain() - - + + B - + B - - - + + + setup_a(std::shared_ptr<detail::A> &) diff --git a/docs/test_cases/t20016.md b/docs/test_cases/t20016.md index 1dd9921c..4ae5396b 100644 --- a/docs/test_cases/t20016.md +++ b/docs/test_cases/t20016.md @@ -54,6 +54,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20016::tmain()", "id": "1912662358651926712", "name": "tmain", "namespace": "clanguml::t20016", @@ -69,6 +70,7 @@ void tmain() "activities": [ { "display_name": "b1(long)", + "full_name": "clanguml::t20016::B::b1(long)", "id": "2064264710178722261", "name": "b1", "namespace": "", @@ -82,6 +84,7 @@ void tmain() }, { "display_name": "b2(long)", + "full_name": "clanguml::t20016::B::b2(long)", "id": "203381140188081853", "name": "b2", "namespace": "", @@ -95,6 +98,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20016::B", "id": "1688340912643326666", "name": "B", "namespace": "clanguml::t20016", @@ -110,6 +114,7 @@ void tmain() "activities": [ { "display_name": "a1(int)", + "full_name": "clanguml::t20016::A::a1(int)", "id": "1198371121423942542", "name": "a1", "namespace": "", @@ -123,6 +128,7 @@ void tmain() }, { "display_name": "a2(const long &)", + "full_name": "clanguml::t20016::A::a2(const long &)", "id": "1208784669530380166", "name": "a2", "namespace": "", @@ -136,6 +142,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20016::A", "id": "1351242594275053195", "name": "A", "namespace": "clanguml::t20016", diff --git a/docs/test_cases/t20016_sequence.svg b/docs/test_cases/t20016_sequence.svg index 5b7605e1..47c0ad3b 100644 --- a/docs/test_cases/t20016_sequence.svg +++ b/docs/test_cases/t20016_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,53 +9,53 @@ - - - - - + + + + + - - + + tmain() - + tmain() - - + + B<long> - + B<long> - - + + A - + A - - - - - - + + + + + + b1(long) - + a1(int) - + b2(long) - + a2(const long &) diff --git a/docs/test_cases/t20017.md b/docs/test_cases/t20017.md index f783f2c3..b3db9d52 100644 --- a/docs/test_cases/t20017.md +++ b/docs/test_cases/t20017.md @@ -77,6 +77,7 @@ template T b2(T x, T y) { return x / y; } "activities": [ { "display_name": "tmain()", + "full_name": "clanguml::t20017::tmain()", "id": "1484746432546296115", "name": "tmain", "namespace": "clanguml::t20017", @@ -90,6 +91,7 @@ template T b2(T x, T y) { return x / y; } } ], "display_name": "t20017.cc", + "full_name": "clanguml::t20017::tmain()", "id": "294332401323799021", "name": "t20017.cc", "namespace": "clanguml::t20017", @@ -99,6 +101,7 @@ template T b2(T x, T y) { return x / y; } "activities": [ { "display_name": "a3(int,int)", + "full_name": "clanguml::t20017::a3(int,int)", "id": "1681392050252260928", "name": "a3", "namespace": "clanguml::t20017", @@ -112,6 +115,7 @@ template T b2(T x, T y) { return x / y; } }, { "display_name": "a2(int,int)", + "full_name": "clanguml::t20017::a2(int,int)", "id": "291553542743365259", "name": "a2", "namespace": "clanguml::t20017", @@ -125,6 +129,7 @@ template T b2(T x, T y) { return x / y; } }, { "display_name": "a1(int,int)", + "full_name": "clanguml::t20017::a1(int,int)", "id": "113759676939330212", "name": "a1", "namespace": "clanguml::t20017", @@ -138,6 +143,7 @@ template T b2(T x, T y) { return x / y; } } ], "display_name": "include/t20017_a.h", + "full_name": "clanguml::t20017::a3(int,int)", "id": "1591222867263639510", "name": "t20017_a.h", "namespace": "clanguml::t20017", @@ -147,6 +153,7 @@ template T b2(T x, T y) { return x / y; } "activities": [ { "display_name": "b1(int,int)", + "full_name": "clanguml::t20017::b1(int,int)", "id": "1714277838806105702", "name": "b1", "namespace": "clanguml::t20017", @@ -160,6 +167,7 @@ template T b2(T x, T y) { return x / y; } }, { "display_name": "b2(int,int)", + "full_name": "clanguml::t20017::b2(int,int)", "id": "775081116464505528", "name": "b2", "namespace": "clanguml::t20017", @@ -173,6 +181,7 @@ template T b2(T x, T y) { return x / y; } } ], "display_name": "include/t20017_b.h", + "full_name": "clanguml::t20017::b1(int,int)", "id": "1113611539183189365", "name": "t20017_b.h", "namespace": "clanguml::t20017", diff --git a/docs/test_cases/t20017_sequence.svg b/docs/test_cases/t20017_sequence.svg index 3af71db0..24207b4a 100644 --- a/docs/test_cases/t20017_sequence.svg +++ b/docs/test_cases/t20017_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,65 +9,65 @@ - - - - - - + + + + + + - + t20017.cc - + t20017.cc - + include/t20017_a.h - + include/t20017_a.h - + include/t20017_b.h - + include/t20017_b.h - - - - - - + + + + + + tmain() - + a3(int,int) - + b1(int,int) - + a2(int,int) - + a1(int,int) - + b2<int>(int,int) diff --git a/docs/test_cases/t20018.md b/docs/test_cases/t20018.md index 79814f4e..fb4c5e30 100644 --- a/docs/test_cases/t20018.md +++ b/docs/test_cases/t20018.md @@ -56,6 +56,7 @@ void tmain() { Answer>::print(); } "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20018::tmain()", "id": "227581758025403815", "name": "tmain", "namespace": "clanguml::t20018", @@ -71,6 +72,7 @@ void tmain() { Answer>::print(); } "activities": [ { "display_name": "print()", + "full_name": "clanguml::t20018::Answer,120>::print()", "id": "1185770766239304952", "name": "print", "namespace": "", @@ -84,6 +86,7 @@ void tmain() { Answer>::print(); } } ], "display_name": "Answer,120>", + "full_name": "clanguml::t20018::Answer,120>", "id": "1163521725351533502", "name": "Answer", "namespace": "clanguml::t20018", @@ -99,6 +102,7 @@ void tmain() { Answer>::print(); } "activities": [ { "display_name": "print(int)", + "full_name": "clanguml::t20018::Factorial<5>::print(int)", "id": "833100888453299461", "name": "print", "namespace": "", @@ -112,6 +116,7 @@ void tmain() { Answer>::print(); } } ], "display_name": "Factorial<5>", + "full_name": "clanguml::t20018::Factorial<5>", "id": "1482779373563849921", "name": "Factorial", "namespace": "clanguml::t20018", @@ -127,6 +132,7 @@ void tmain() { Answer>::print(); } "activities": [ { "display_name": "print(int)", + "full_name": "clanguml::t20018::Factorial<4>::print(int)", "id": "1782586643813991247", "name": "print", "namespace": "", @@ -140,6 +146,7 @@ void tmain() { Answer>::print(); } } ], "display_name": "Factorial<4>", + "full_name": "clanguml::t20018::Factorial<4>", "id": "52416404065514823", "name": "Factorial", "namespace": "clanguml::t20018", @@ -155,6 +162,7 @@ void tmain() { Answer>::print(); } "activities": [ { "display_name": "print(int)", + "full_name": "clanguml::t20018::Factorial<3>::print(int)", "id": "1238078028595736678", "name": "print", "namespace": "", @@ -168,6 +176,7 @@ void tmain() { Answer>::print(); } } ], "display_name": "Factorial<3>", + "full_name": "clanguml::t20018::Factorial<3>", "id": "1658728078296100018", "name": "Factorial", "namespace": "clanguml::t20018", @@ -183,6 +192,7 @@ void tmain() { Answer>::print(); } "activities": [ { "display_name": "print(int)", + "full_name": "clanguml::t20018::Factorial<2>::print(int)", "id": "2163270950475476780", "name": "print", "namespace": "", @@ -196,6 +206,7 @@ void tmain() { Answer>::print(); } } ], "display_name": "Factorial<2>", + "full_name": "clanguml::t20018::Factorial<2>", "id": "969903469166760124", "name": "Factorial", "namespace": "clanguml::t20018", @@ -211,6 +222,7 @@ void tmain() { Answer>::print(); } "activities": [ { "display_name": "print(int)", + "full_name": "clanguml::t20018::Factorial<1>::print(int)", "id": "501166016325937670", "name": "print", "namespace": "", @@ -224,6 +236,7 @@ void tmain() { Answer>::print(); } } ], "display_name": "Factorial<1>", + "full_name": "clanguml::t20018::Factorial<1>", "id": "2032621198190600516", "name": "Factorial", "namespace": "clanguml::t20018", @@ -239,6 +252,7 @@ void tmain() { Answer>::print(); } "activities": [ { "display_name": "print(int)", + "full_name": "clanguml::t20018::Factorial<0>::print(int)", "id": "577232827352391544", "name": "print", "namespace": "", @@ -252,6 +266,7 @@ void tmain() { Answer>::print(); } } ], "display_name": "Factorial<0>", + "full_name": "clanguml::t20018::Factorial<0>", "id": "1581865799666386458", "name": "Factorial", "namespace": "clanguml::t20018", diff --git a/docs/test_cases/t20018_sequence.svg b/docs/test_cases/t20018_sequence.svg index 2ade440b..6b7fcbdc 100644 --- a/docs/test_cases/t20018_sequence.svg +++ b/docs/test_cases/t20018_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,14 +9,14 @@ - - - - - - - - + + + + + + + + @@ -25,93 +25,93 @@ - - + + tmain() - + tmain() - - + + Answer<Factorial<5>,120> - + Answer<Factorial<5>,120> - - + + Factorial<5> - + Factorial<5> - - + + Factorial<4> - + Factorial<4> - - + + Factorial<3> - + Factorial<3> - - + + Factorial<2> - + Factorial<2> - - + + Factorial<1> - + Factorial<1> - - + + Factorial<0> - + Factorial<0> - - - - - - - - - + + + + + + + + + print() - + print(int) - + print(int) - + print(int) - + print(int) - + print(int) - + print(int) diff --git a/docs/test_cases/t20019.md b/docs/test_cases/t20019.md index b8f1358d..b8a58ad4 100644 --- a/docs/test_cases/t20019.md +++ b/docs/test_cases/t20019.md @@ -63,6 +63,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20019::tmain()", "id": "375304196268652861", "name": "tmain", "namespace": "clanguml::t20019", @@ -78,6 +79,7 @@ void tmain() "activities": [ { "display_name": "name()", + "full_name": "clanguml::t20019::Base::name()", "id": "1038853547136467401", "name": "name", "namespace": "", @@ -91,6 +93,7 @@ void tmain() } ], "display_name": "Base", + "full_name": "clanguml::t20019::Base", "id": "381327373934972004", "name": "Base", "namespace": "clanguml::t20019", @@ -106,6 +109,7 @@ void tmain() "activities": [ { "display_name": "impl()", + "full_name": "clanguml::t20019::D1::impl()", "id": "603969604599968603", "name": "impl", "namespace": "", @@ -119,6 +123,7 @@ void tmain() } ], "display_name": "D1", + "full_name": "clanguml::t20019::D1", "id": "1282259011856139592", "name": "D1", "namespace": "clanguml::t20019", @@ -134,6 +139,7 @@ void tmain() "activities": [ { "display_name": "name()", + "full_name": "clanguml::t20019::Base::name()", "id": "1918672956676175365", "name": "name", "namespace": "", @@ -147,6 +153,7 @@ void tmain() } ], "display_name": "Base", + "full_name": "clanguml::t20019::Base", "id": "1659477498076328530", "name": "Base", "namespace": "clanguml::t20019", @@ -162,6 +169,7 @@ void tmain() "activities": [ { "display_name": "impl()", + "full_name": "clanguml::t20019::D2::impl()", "id": "861400435979772695", "name": "impl", "namespace": "", @@ -175,6 +183,7 @@ void tmain() } ], "display_name": "D2", + "full_name": "clanguml::t20019::D2", "id": "1307471723138212117", "name": "D2", "namespace": "clanguml::t20019", @@ -290,6 +299,26 @@ void tmain() }, "type": "message" }, + { + "from": { + "activity_id": "1038853547136467401", + "participant_id": "381327373934972004" + }, + "name": "impl()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 19, + "file": "t20019.cc", + "line": 9, + "translation_unit": "t20019.cc" + }, + "to": { + "activity_id": "603969604599968603", + "participant_id": "1282259011856139592" + }, + "type": "message" + }, { "from": { "activity_id": "375304196268652861", @@ -309,6 +338,26 @@ void tmain() "participant_id": "1659477498076328530" }, "type": "message" + }, + { + "from": { + "activity_id": "1918672956676175365", + "participant_id": "1659477498076328530" + }, + "name": "impl()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 19, + "file": "t20019.cc", + "line": 9, + "translation_unit": "t20019.cc" + }, + "to": { + "activity_id": "861400435979772695", + "participant_id": "1307471723138212117" + }, + "type": "message" } ], "start_from": { diff --git a/docs/test_cases/t20019_sequence.svg b/docs/test_cases/t20019_sequence.svg index a1468b6b..fe83b99e 100644 --- a/docs/test_cases/t20019_sequence.svg +++ b/docs/test_cases/t20019_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,95 +9,95 @@ - - - - - - - - - + + + + + + + + + - - + + tmain() - + tmain() - - + + Base<D1> - + Base<D1> - - + + D1 - + D1 - - + + Base<D2> - + Base<D2> - - + + D2 - + D2 - - - - - - - - - - + + + + + + + + + + name() - + impl() - + name() - + impl() - + name() - + impl() - + name() - + impl() diff --git a/docs/test_cases/t20020.md b/docs/test_cases/t20020.md index 26b80d87..891e9311 100644 --- a/docs/test_cases/t20020.md +++ b/docs/test_cases/t20020.md @@ -119,6 +119,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20020::tmain()", "id": "432124388562400664", "name": "tmain", "namespace": "clanguml::t20020", @@ -134,6 +135,7 @@ int tmain() "activities": [ { "display_name": "a1()", + "full_name": "clanguml::t20020::A::a1()", "id": "43928675765534701", "name": "a1", "namespace": "", @@ -147,6 +149,7 @@ int tmain() }, { "display_name": "a5()", + "full_name": "clanguml::t20020::A::a5()", "id": "1613457246223182826", "name": "a5", "namespace": "", @@ -160,6 +163,7 @@ int tmain() }, { "display_name": "a2()", + "full_name": "clanguml::t20020::A::a2()", "id": "1289745252290688140", "name": "a2", "namespace": "", @@ -173,6 +177,7 @@ int tmain() }, { "display_name": "a3()", + "full_name": "clanguml::t20020::A::a3()", "id": "1983660679554669898", "name": "a3", "namespace": "", @@ -186,6 +191,7 @@ int tmain() }, { "display_name": "a4()", + "full_name": "clanguml::t20020::A::a4()", "id": "20573198999978866", "name": "a4", "namespace": "", @@ -199,6 +205,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20020::A", "id": "208941846648931609", "name": "A", "namespace": "clanguml::t20020", @@ -214,6 +221,7 @@ int tmain() "activities": [ { "display_name": "c3(int)", + "full_name": "clanguml::t20020::C::c3(int)", "id": "1303438784842196201", "name": "c3", "namespace": "", @@ -227,6 +235,7 @@ int tmain() }, { "display_name": "c1() const", + "full_name": "clanguml::t20020::C::c1() const", "id": "1473521613404783653", "name": "c1", "namespace": "", @@ -240,6 +249,7 @@ int tmain() }, { "display_name": "c2() const", + "full_name": "clanguml::t20020::C::c2() const", "id": "1789116382725485914", "name": "c2", "namespace": "", @@ -253,6 +263,7 @@ int tmain() }, { "display_name": "log() const", + "full_name": "clanguml::t20020::C::log() const", "id": "635780525021572670", "name": "log", "namespace": "", @@ -266,6 +277,7 @@ int tmain() } ], "display_name": "C", + "full_name": "clanguml::t20020::C", "id": "1562462306909405383", "name": "C", "namespace": "clanguml::t20020", @@ -281,6 +293,7 @@ int tmain() "activities": [ { "display_name": "b1()", + "full_name": "clanguml::t20020::B::b1()", "id": "542196582335607343", "name": "b1", "namespace": "", @@ -294,6 +307,7 @@ int tmain() }, { "display_name": "b2()", + "full_name": "clanguml::t20020::B::b2()", "id": "505760236964179187", "name": "b2", "namespace": "", @@ -307,6 +321,7 @@ int tmain() }, { "display_name": "log()", + "full_name": "clanguml::t20020::B::log()", "id": "1436250788704205026", "name": "log", "namespace": "", @@ -320,6 +335,7 @@ int tmain() } ], "display_name": "B", + "full_name": "clanguml::t20020::B", "id": "1342563483612170412", "name": "B", "namespace": "clanguml::t20020", @@ -335,6 +351,7 @@ int tmain() "activities": [ { "display_name": "d1(int,int)", + "full_name": "clanguml::t20020::D::d1(int,int)", "id": "1780002010052842766", "name": "d1", "namespace": "", @@ -348,6 +365,7 @@ int tmain() } ], "display_name": "D", + "full_name": "clanguml::t20020::D", "id": "1605914310746811866", "name": "D", "namespace": "clanguml::t20020", diff --git a/docs/test_cases/t20020_sequence.svg b/docs/test_cases/t20020_sequence.svg index 584640eb..2ec208d6 100644 --- a/docs/test_cases/t20020_sequence.svg +++ b/docs/test_cases/t20020_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,82 +9,82 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - - - + + + - - + + tmain() - + tmain() - - + + A - + A - - + + C - + C - - + + B - + B - - + + D<int> - + D<int> - - - - - - - - - - - - - - + + + + + + + + + + + + + + alt - + a1() @@ -92,7 +92,7 @@ - + a5() @@ -103,7 +103,7 @@ alt - + [ @@ -112,7 +112,7 @@ - + [ @@ -121,7 +121,7 @@ - + b1() @@ -129,7 +129,7 @@ - + [ @@ -138,7 +138,7 @@ - + b2() @@ -146,14 +146,14 @@ - + a4() - + log() @@ -161,7 +161,7 @@ alt - + c1() const @@ -169,7 +169,7 @@ alt - + @@ -182,7 +182,7 @@ - + @@ -192,7 +192,7 @@ alt - + d1(int,int) diff --git a/docs/test_cases/t20021.md b/docs/test_cases/t20021.md index aaa507b9..64a335e5 100644 --- a/docs/test_cases/t20021.md +++ b/docs/test_cases/t20021.md @@ -86,6 +86,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20021::tmain()", "id": "1682631020380557915", "name": "tmain", "namespace": "clanguml::t20021", @@ -101,6 +102,7 @@ int tmain() "activities": [ { "display_name": "c4()", + "full_name": "clanguml::t20021::C::c4()", "id": "124927877622321176", "name": "c4", "namespace": "", @@ -114,6 +116,7 @@ int tmain() }, { "display_name": "c5()", + "full_name": "clanguml::t20021::C::c5()", "id": "1325720714179808628", "name": "c5", "namespace": "", @@ -127,6 +130,7 @@ int tmain() }, { "display_name": "c1()", + "full_name": "clanguml::t20021::C::c1()", "id": "2143764740072323303", "name": "c1", "namespace": "", @@ -140,6 +144,7 @@ int tmain() }, { "display_name": "c2()", + "full_name": "clanguml::t20021::C::c2()", "id": "1707693479408501017", "name": "c2", "namespace": "", @@ -153,6 +158,7 @@ int tmain() }, { "display_name": "c3()", + "full_name": "clanguml::t20021::C::c3()", "id": "1302892753246800390", "name": "c3", "namespace": "", @@ -166,6 +172,7 @@ int tmain() }, { "display_name": "contents()", + "full_name": "clanguml::t20021::C::contents()", "id": "814405216385697964", "name": "contents", "namespace": "", @@ -179,6 +186,7 @@ int tmain() } ], "display_name": "C", + "full_name": "clanguml::t20021::C", "id": "451128000259357438", "name": "C", "namespace": "clanguml::t20021", @@ -194,6 +202,7 @@ int tmain() "activities": [ { "display_name": "a3()", + "full_name": "clanguml::t20021::A::a3()", "id": "1867955233624891190", "name": "a3", "namespace": "", @@ -207,6 +216,7 @@ int tmain() }, { "display_name": "a2()", + "full_name": "clanguml::t20021::A::a2()", "id": "1139294797758415018", "name": "a2", "namespace": "", @@ -220,6 +230,7 @@ int tmain() }, { "display_name": "a1()", + "full_name": "clanguml::t20021::A::a1()", "id": "1659488549696810992", "name": "a1", "namespace": "", @@ -233,6 +244,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20021::A", "id": "1280483607329510730", "name": "A", "namespace": "clanguml::t20021", @@ -248,6 +260,7 @@ int tmain() "activities": [ { "display_name": "b2() const", + "full_name": "clanguml::t20021::B::b2() const", "id": "1561040999276563077", "name": "b2", "namespace": "", @@ -261,6 +274,7 @@ int tmain() } ], "display_name": "B", + "full_name": "clanguml::t20021::B", "id": "1849696080443395393", "name": "B", "namespace": "clanguml::t20021", diff --git a/docs/test_cases/t20021_sequence.svg b/docs/test_cases/t20021_sequence.svg index fca3ac8e..b739f2b0 100644 --- a/docs/test_cases/t20021_sequence.svg +++ b/docs/test_cases/t20021_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,74 +9,74 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + + tmain() - + tmain() - - + + C - + C - - + + A - + A - - + + B - + B - - - - - - - - - - - - + + + + + + + + + + + + loop - + [ c4() ] - + @@ -89,7 +89,7 @@ - + a3() @@ -102,7 +102,7 @@ loop - + [ @@ -111,7 +111,7 @@ - + [ @@ -120,7 +120,7 @@ - + [ @@ -129,14 +129,14 @@ - + a1() - + [ @@ -148,7 +148,7 @@ loop - + b2() const @@ -158,7 +158,7 @@ loop - + [ @@ -167,7 +167,7 @@ - + b2() const diff --git a/docs/test_cases/t20022.md b/docs/test_cases/t20022.md index 3a5b201f..f359bdc8 100644 --- a/docs/test_cases/t20022.md +++ b/docs/test_cases/t20022.md @@ -66,6 +66,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20022::tmain()", "id": "1374011101998494743", "name": "tmain", "namespace": "clanguml::t20022", @@ -81,6 +82,7 @@ int tmain() "activities": [ { "display_name": "A(std::unique_ptr)", + "full_name": "clanguml::t20022::A::A(std::unique_ptr)", "id": "1226569306557207632", "name": "A", "namespace": "", @@ -94,6 +96,7 @@ int tmain() }, { "display_name": "a()", + "full_name": "clanguml::t20022::A::a()", "id": "1158824701633811441", "name": "a", "namespace": "", @@ -107,6 +110,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20022::A", "id": "1535467498096081224", "name": "A", "namespace": "clanguml::t20022", @@ -122,6 +126,7 @@ int tmain() "activities": [ { "display_name": "b()", + "full_name": "clanguml::t20022::B::b()", "id": "2114222968575993291", "name": "b", "namespace": "", @@ -135,6 +140,7 @@ int tmain() } ], "display_name": "B", + "full_name": "clanguml::t20022::B", "id": "1316821731069034940", "name": "B", "namespace": "clanguml::t20022", diff --git a/docs/test_cases/t20022_sequence.svg b/docs/test_cases/t20022_sequence.svg index b400c21a..cae87180 100644 --- a/docs/test_cases/t20022_sequence.svg +++ b/docs/test_cases/t20022_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,47 +9,47 @@ - - - - + + + + - - + + tmain() - + tmain() - - + + A - + A - - + + B - + B - - - - - + + + + + A(std::unique_ptr ) - + a() - + b() diff --git a/docs/test_cases/t20023.md b/docs/test_cases/t20023.md index badfc94d..bdcac722 100644 --- a/docs/test_cases/t20023.md +++ b/docs/test_cases/t20023.md @@ -69,6 +69,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20023::tmain()", "id": "761552264135157511", "name": "tmain", "namespace": "clanguml::t20023", @@ -84,6 +85,7 @@ int tmain() "activities": [ { "display_name": "a()", + "full_name": "clanguml::t20023::A::a()", "id": "530651320277188697", "name": "a", "namespace": "", @@ -97,6 +99,7 @@ int tmain() }, { "display_name": "a1()", + "full_name": "clanguml::t20023::A::a1()", "id": "94135113932519208", "name": "a1", "namespace": "", @@ -110,6 +113,7 @@ int tmain() }, { "display_name": "a2()", + "full_name": "clanguml::t20023::A::a2()", "id": "2060438178899014465", "name": "a2", "namespace": "", @@ -123,6 +127,7 @@ int tmain() }, { "display_name": "a3()", + "full_name": "clanguml::t20023::A::a3()", "id": "1776927259621603017", "name": "a3", "namespace": "", @@ -136,6 +141,7 @@ int tmain() }, { "display_name": "a4()", + "full_name": "clanguml::t20023::A::a4()", "id": "1082587698374248813", "name": "a4", "namespace": "", @@ -149,6 +155,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20023::A", "id": "750638294800359616", "name": "A", "namespace": "clanguml::t20023", diff --git a/docs/test_cases/t20023_sequence.svg b/docs/test_cases/t20023_sequence.svg index d655ec9c..50295a7a 100644 --- a/docs/test_cases/t20023_sequence.svg +++ b/docs/test_cases/t20023_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,37 +9,37 @@ - - - - - - - + + + + + + + - - + + tmain() - + tmain() - - + + A - + A - - - - - - - + + + + + + + a() @@ -47,7 +47,7 @@ try - + @@ -60,7 +60,7 @@ [std::runtime_error &] - + @@ -73,7 +73,7 @@ [std::logic_error &] - + @@ -86,7 +86,7 @@ [...] - + diff --git a/docs/test_cases/t20024.md b/docs/test_cases/t20024.md index 83fdb4c9..165f4a38 100644 --- a/docs/test_cases/t20024.md +++ b/docs/test_cases/t20024.md @@ -94,6 +94,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20024::tmain()", "id": "1919714441225983014", "name": "tmain", "namespace": "clanguml::t20024", @@ -109,6 +110,7 @@ int tmain() "activities": [ { "display_name": "select(enum_a)", + "full_name": "clanguml::t20024::A::select(enum_a)", "id": "1200587047701031901", "name": "select", "namespace": "", @@ -122,6 +124,7 @@ int tmain() }, { "display_name": "a0()", + "full_name": "clanguml::t20024::A::a0()", "id": "1859614580641799156", "name": "a0", "namespace": "", @@ -135,6 +138,7 @@ int tmain() }, { "display_name": "a1()", + "full_name": "clanguml::t20024::A::a1()", "id": "501598940454911460", "name": "a1", "namespace": "", @@ -148,6 +152,7 @@ int tmain() }, { "display_name": "a2()", + "full_name": "clanguml::t20024::A::a2()", "id": "1698866541173753340", "name": "a2", "namespace": "", @@ -161,6 +166,7 @@ int tmain() }, { "display_name": "a3()", + "full_name": "clanguml::t20024::A::a3()", "id": "490376438551958259", "name": "a3", "namespace": "", @@ -174,6 +180,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20024::A", "id": "40786919835708828", "name": "A", "namespace": "clanguml::t20024", @@ -189,6 +196,7 @@ int tmain() "activities": [ { "display_name": "select(colors)", + "full_name": "clanguml::t20024::B::select(colors)", "id": "286108218156977422", "name": "select", "namespace": "", @@ -202,6 +210,7 @@ int tmain() }, { "display_name": "red()", + "full_name": "clanguml::t20024::B::red()", "id": "112014563206084467", "name": "red", "namespace": "", @@ -215,6 +224,7 @@ int tmain() }, { "display_name": "orange()", + "full_name": "clanguml::t20024::B::orange()", "id": "2222823236498505185", "name": "orange", "namespace": "", @@ -228,6 +238,7 @@ int tmain() }, { "display_name": "green()", + "full_name": "clanguml::t20024::B::green()", "id": "519021723720658376", "name": "green", "namespace": "", @@ -241,6 +252,7 @@ int tmain() }, { "display_name": "grey()", + "full_name": "clanguml::t20024::B::grey()", "id": "1813557671878544737", "name": "grey", "namespace": "", @@ -254,6 +266,7 @@ int tmain() } ], "display_name": "B", + "full_name": "clanguml::t20024::B", "id": "933287014626440872", "name": "B", "namespace": "clanguml::t20024", diff --git a/docs/test_cases/t20024_sequence.svg b/docs/test_cases/t20024_sequence.svg index ae2b817a..5e530bd7 100644 --- a/docs/test_cases/t20024_sequence.svg +++ b/docs/test_cases/t20024_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,23 +9,23 @@ - - - - - - - - - - - - + + + + + + + + + + + + - + @@ -33,36 +33,36 @@ - - + + tmain() - + tmain() - - + + A - + A - - + + B - + B - - - - - - - - - - - - + + + + + + + + + + + + select(enum_a) @@ -72,7 +72,7 @@ switch [zero] - + @@ -85,7 +85,7 @@ [one] - + @@ -98,7 +98,7 @@ [two] - + @@ -111,7 +111,7 @@ [default] - + @@ -124,7 +124,7 @@ - + select(colors) @@ -134,7 +134,7 @@ switch [enum colors::red] - + @@ -143,7 +143,7 @@ [enum colors::orange] - + @@ -152,7 +152,7 @@ [enum colors::green] - + @@ -161,7 +161,7 @@ [default] - + diff --git a/docs/test_cases/t20025.md b/docs/test_cases/t20025.md index fccaf773..58d9263c 100644 --- a/docs/test_cases/t20025.md +++ b/docs/test_cases/t20025.md @@ -74,6 +74,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20025::tmain()", "id": "1268545806896171690", "name": "tmain", "namespace": "clanguml::t20025", @@ -89,6 +90,7 @@ int tmain() "activities": [ { "display_name": "a()", + "full_name": "clanguml::t20025::A::a()", "id": "1119830104994271584", "name": "a", "namespace": "", @@ -102,6 +104,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20025::A", "id": "2144852170258286289", "name": "A", "namespace": "clanguml::t20025", @@ -115,6 +118,7 @@ int tmain() }, { "display_name": "add(int,int)", + "full_name": "clanguml::t20025::add(int,int)", "id": "228843323046630374", "name": "add", "namespace": "clanguml::t20025", diff --git a/docs/test_cases/t20025_sequence.svg b/docs/test_cases/t20025_sequence.svg index 572ac89f..7c246eac 100644 --- a/docs/test_cases/t20025_sequence.svg +++ b/docs/test_cases/t20025_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,41 +9,41 @@ - - - + + + - - + + tmain() - + tmain() - - + + A - + A - - + + add(int,int) - + add(int,int) - - - - + + + + a() - + diff --git a/docs/test_cases/t20026.md b/docs/test_cases/t20026.md index dcb559c4..8f0091ce 100644 --- a/docs/test_cases/t20026.md +++ b/docs/test_cases/t20026.md @@ -54,6 +54,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20026::tmain()", "id": "2268697350307997040", "name": "tmain", "namespace": "clanguml::t20026", @@ -69,6 +70,7 @@ int tmain() "activities": [ { "display_name": "a()", + "full_name": "clanguml::t20026::A::a()", "id": "600590770418147864", "name": "a", "namespace": "", @@ -82,6 +84,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20026::A", "id": "1962121823853291899", "name": "A", "namespace": "clanguml::t20026", diff --git a/docs/test_cases/t20026_sequence.svg b/docs/test_cases/t20026_sequence.svg index 0fadbd52..d4b71277 100644 --- a/docs/test_cases/t20026_sequence.svg +++ b/docs/test_cases/t20026_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,25 +9,25 @@ - - + + - - + + tmain() - + tmain() - - + + A - + A - - - + + + a() diff --git a/docs/test_cases/t20027.md b/docs/test_cases/t20027.md index debe9624..62a2af3e 100644 --- a/docs/test_cases/t20027.md +++ b/docs/test_cases/t20027.md @@ -53,6 +53,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20027::tmain()", "id": "1581009482994430286", "name": "tmain", "namespace": "clanguml::t20027", @@ -68,6 +69,7 @@ void tmain() "activities": [ { "display_name": "a()", + "full_name": "clanguml::t20027::A::a()", "id": "910514967786202717", "name": "a", "namespace": "", @@ -81,6 +83,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20027::A", "id": "583525629936262089", "name": "A", "namespace": "clanguml::t20027", diff --git a/docs/test_cases/t20027_sequence.svg b/docs/test_cases/t20027_sequence.svg index f5e8c321..3fd15dee 100644 --- a/docs/test_cases/t20027_sequence.svg +++ b/docs/test_cases/t20027_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,25 +9,25 @@ - - + + - - + + tmain() - + tmain() - - + + A - + A - - - + + + a() diff --git a/docs/test_cases/t20028.md b/docs/test_cases/t20028.md index 9f698cdd..3d05d652 100644 --- a/docs/test_cases/t20028.md +++ b/docs/test_cases/t20028.md @@ -63,6 +63,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20028::tmain()", "id": "1347206662193933194", "name": "tmain", "namespace": "clanguml::t20028", @@ -78,6 +79,7 @@ int tmain() "activities": [ { "display_name": "a()", + "full_name": "clanguml::t20028::A::a()", "id": "666210834901940781", "name": "a", "namespace": "", @@ -91,6 +93,7 @@ int tmain() }, { "display_name": "b()", + "full_name": "clanguml::t20028::A::b()", "id": "793793464184037795", "name": "b", "namespace": "", @@ -104,6 +107,7 @@ int tmain() }, { "display_name": "c()", + "full_name": "clanguml::t20028::A::c()", "id": "1582152567698110078", "name": "c", "namespace": "", @@ -117,6 +121,7 @@ int tmain() }, { "display_name": "d()", + "full_name": "clanguml::t20028::A::d()", "id": "1178268687951492696", "name": "d", "namespace": "", @@ -130,6 +135,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20028::A", "id": "2073479923903128898", "name": "A", "namespace": "clanguml::t20028", diff --git a/docs/test_cases/t20028_sequence.svg b/docs/test_cases/t20028_sequence.svg index 244fe608..cd54101c 100644 --- a/docs/test_cases/t20028_sequence.svg +++ b/docs/test_cases/t20028_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,36 +9,36 @@ - - - - - - + + + + + + - - + + tmain() - + tmain() - - + + A - + A - - - - - + + + + + alt - + [ @@ -47,14 +47,14 @@ - + b() - + c() @@ -62,7 +62,7 @@ - + d() diff --git a/docs/test_cases/t20029.md b/docs/test_cases/t20029.md index 5adbaa45..de6b7136 100644 --- a/docs/test_cases/t20029.md +++ b/docs/test_cases/t20029.md @@ -116,6 +116,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20029::tmain()", "id": "2091374738808319642", "name": "tmain", "namespace": "clanguml::t20029", @@ -131,6 +132,7 @@ int tmain() "activities": [ { "display_name": "send(std::string &&)", + "full_name": "clanguml::t20029::Encoder>::send(std::string &&)", "id": "2026763864005979273", "name": "send", "namespace": "", @@ -144,6 +146,7 @@ int tmain() }, { "display_name": "encode(std::string &&)", + "full_name": "clanguml::t20029::Encoder>::encode(std::string &&)", "id": "1468258269466480773", "name": "encode", "namespace": "", @@ -157,6 +160,7 @@ int tmain() } ], "display_name": "Encoder>", + "full_name": "clanguml::t20029::Encoder>", "id": "1673261195873192383", "name": "Encoder", "namespace": "clanguml::t20029", @@ -172,6 +176,7 @@ int tmain() "activities": [ { "display_name": "send(std::string &&)", + "full_name": "clanguml::t20029::Retrier::send(std::string &&)", "id": "30515971485361302", "name": "send", "namespace": "", @@ -185,6 +190,7 @@ int tmain() } ], "display_name": "Retrier", + "full_name": "clanguml::t20029::Retrier", "id": "658058855590948094", "name": "Retrier", "namespace": "clanguml::t20029", @@ -200,6 +206,7 @@ int tmain() "activities": [ { "display_name": "connect()", + "full_name": "clanguml::t20029::ConnectionPool::connect()", "id": "940428568182104530", "name": "connect", "namespace": "", @@ -213,6 +220,7 @@ int tmain() }, { "display_name": "send(const std::string &)", + "full_name": "clanguml::t20029::ConnectionPool::send(const std::string &)", "id": "972625940114169157", "name": "send", "namespace": "", @@ -226,6 +234,7 @@ int tmain() } ], "display_name": "ConnectionPool", + "full_name": "clanguml::t20029::ConnectionPool", "id": "1896406205097618937", "name": "ConnectionPool", "namespace": "clanguml::t20029", @@ -239,6 +248,7 @@ int tmain() }, { "display_name": "encode_b64(std::string &&)", + "full_name": "clanguml::t20029::encode_b64(std::string &&)", "id": "1362646431260879440", "name": "encode_b64", "namespace": "clanguml::t20029", diff --git a/docs/test_cases/t20029_sequence.svg b/docs/test_cases/t20029_sequence.svg index a42f248b..4ed69218 100644 --- a/docs/test_cases/t20029_sequence.svg +++ b/docs/test_cases/t20029_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,69 +9,69 @@ - - - - - - - - - - - + + + + + + + + + + + - - + + tmain() - + tmain() - - + + Encoder<Retrier<ConnectionPool>> - + Encoder<Retrier<ConnectionPool>> - - + + Retrier<ConnectionPool> - + Retrier<ConnectionPool> - - + + ConnectionPool - + ConnectionPool - - + + encode_b64(std::string &&) - + encode_b64(std::string &&) - - - - - - - - + + + + + + + + Establish connection to the remote server synchronously - + connect() - + Repeat for each line in the input stream @@ -81,26 +81,26 @@ alt - + [ send(std::string &&) ] - + Encode the message using Base64 encoding and pass it to the next layer - + encode(std::string &&) - + @@ -110,12 +110,12 @@ - + send(std::string &&) - + Repeat until send() succeeds or retry count is exceeded @@ -125,7 +125,7 @@ alt - + [ diff --git a/docs/test_cases/t20030.md b/docs/test_cases/t20030.md index 1046ed4f..462dc69a 100644 --- a/docs/test_cases/t20030.md +++ b/docs/test_cases/t20030.md @@ -81,6 +81,7 @@ int tmain(bool f, int a) "participants": [ { "display_name": "tmain(int)", + "full_name": "clanguml::t20030::tmain(int)", "id": "1264643561983920529", "name": "tmain", "namespace": "clanguml::t20030", @@ -94,6 +95,7 @@ int tmain(bool f, int a) }, { "display_name": "magic()", + "full_name": "clanguml::t20030::magic()", "id": "1038740565367213967", "name": "magic", "namespace": "clanguml::t20030", @@ -109,6 +111,7 @@ int tmain(bool f, int a) "activities": [ { "display_name": "A(int)", + "full_name": "clanguml::t20030::A::A(int)", "id": "2192298168642377389", "name": "A", "namespace": "", @@ -122,6 +125,7 @@ int tmain(bool f, int a) }, { "display_name": "operator+=(int)", + "full_name": "clanguml::t20030::A::operator+=(int)", "id": "2032167997122548080", "name": "operator+=", "namespace": "", @@ -135,6 +139,7 @@ int tmain(bool f, int a) }, { "display_name": "add(int)", + "full_name": "clanguml::t20030::A::add(int)", "id": "2174827432067616124", "name": "add", "namespace": "", @@ -148,6 +153,7 @@ int tmain(bool f, int a) }, { "display_name": "A()", + "full_name": "clanguml::t20030::A::A()", "id": "32184916294885915", "name": "A", "namespace": "", @@ -161,6 +167,7 @@ int tmain(bool f, int a) }, { "display_name": "create()", + "full_name": "clanguml::t20030::A::create()", "id": "890578100069139188", "name": "create", "namespace": "", @@ -174,6 +181,7 @@ int tmain(bool f, int a) }, { "display_name": "operator=(const A &)", + "full_name": "clanguml::t20030::A::operator=(const A &)", "id": "1796303685088700396", "name": "operator=", "namespace": "", @@ -187,6 +195,7 @@ int tmain(bool f, int a) }, { "display_name": "set(int)", + "full_name": "clanguml::t20030::A::set(int)", "id": "2212978510776223413", "name": "set", "namespace": "", @@ -200,6 +209,7 @@ int tmain(bool f, int a) }, { "display_name": "value() const", + "full_name": "clanguml::t20030::A::value() const", "id": "1754957340376276968", "name": "value", "namespace": "", @@ -213,6 +223,7 @@ int tmain(bool f, int a) } ], "display_name": "A", + "full_name": "clanguml::t20030::A", "id": "1081707114848460702", "name": "A", "namespace": "clanguml::t20030", @@ -226,6 +237,7 @@ int tmain(bool f, int a) }, { "display_name": "tmain(bool,int)", + "full_name": "clanguml::t20030::tmain(bool,int)", "id": "36090614888670483", "name": "tmain", "namespace": "clanguml::t20030", @@ -389,6 +401,26 @@ int tmain(bool f, int a) }, "type": "message" }, + { + "from": { + "activity_id": "32184916294885915", + "participant_id": "1081707114848460702" + }, + "name": "create()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 11, + "file": "t20030.cc", + "line": 8, + "translation_unit": "t20030.cc" + }, + "to": { + "activity_id": "890578100069139188", + "participant_id": "1081707114848460702" + }, + "type": "message" + }, { "from": { "activity_id": "36090614888670483", diff --git a/docs/test_cases/t20030_sequence.svg b/docs/test_cases/t20030_sequence.svg index c7901eee..76187b59 100644 --- a/docs/test_cases/t20030_sequence.svg +++ b/docs/test_cases/t20030_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,81 +9,81 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + tmain(int) - + tmain(int) - - + + magic() - + magic() - - + + A - + A - - + + tmain(bool,int) - + tmain(bool,int) - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + A(int) - + operator+=(int) - + @@ -92,36 +92,36 @@ - + A() - + create() - + A() - + create() - + operator+=(int) - + @@ -130,12 +130,12 @@ - + operator=(const A &) - + @@ -144,7 +144,7 @@ - + value() const diff --git a/docs/test_cases/t20031.md b/docs/test_cases/t20031.md index 90ac6d95..8122b515 100644 --- a/docs/test_cases/t20031.md +++ b/docs/test_cases/t20031.md @@ -97,6 +97,7 @@ int tmain(bool f, int a) "participants": [ { "display_name": "tmain(int)", + "full_name": "clanguml::t20031::tmain(int)", "id": "1045973591033429178", "name": "tmain", "namespace": "clanguml::t20031", @@ -110,6 +111,7 @@ int tmain(bool f, int a) }, { "display_name": "magic()", + "full_name": "clanguml::t20031::magic()", "id": "2265790048300959619", "name": "magic", "namespace": "clanguml::t20031", @@ -123,6 +125,7 @@ int tmain(bool f, int a) }, { "display_name": "tmain(bool,int)", + "full_name": "clanguml::t20031::tmain(bool,int)", "id": "2189754495514350927", "name": "tmain", "namespace": "clanguml::t20031", @@ -136,6 +139,7 @@ int tmain(bool f, int a) }, { "display_name": "execute(std::function)", + "full_name": "clanguml::t20031::execute(std::function)", "id": "2230160420908832598", "name": "execute", "namespace": "clanguml::t20031", @@ -151,6 +155,7 @@ int tmain(bool f, int a) "activities": [ { "display_name": "value() const", + "full_name": "clanguml::t20031::A::value() const", "id": "1089278431155817348", "name": "value", "namespace": "", @@ -164,6 +169,7 @@ int tmain(bool f, int a) } ], "display_name": "A", + "full_name": "clanguml::t20031::A", "id": "1081580052625775404", "name": "A", "namespace": "clanguml::t20031", diff --git a/docs/test_cases/t20031_sequence.svg b/docs/test_cases/t20031_sequence.svg index 40b7ac7f..58c30a08 100644 --- a/docs/test_cases/t20031_sequence.svg +++ b/docs/test_cases/t20031_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,64 +9,64 @@ - - - - - + + + + + - - + + tmain(int) - + tmain(int) - - + + magic() - + magic() - - + + tmain(bool,int) - + tmain(bool,int) - - + + execute(std::function<int ()>) - + execute(std::function<int ()>) - - + + A - + A - - - - - - + + + + + + - + - + value() const diff --git a/docs/test_cases/t20032.md b/docs/test_cases/t20032.md index 2692af8c..fc54366c 100644 --- a/docs/test_cases/t20032.md +++ b/docs/test_cases/t20032.md @@ -57,6 +57,7 @@ void tmain(int argc, char **argv) "participants": [ { "display_name": "tmain(int,char **)", + "full_name": "clanguml::t20032::tmain(int,char **)", "id": "2159371207846335450", "name": "tmain", "namespace": "clanguml::t20032", @@ -72,6 +73,7 @@ void tmain(int argc, char **argv) "activities": [ { "display_name": "b(int)", + "full_name": "clanguml::t20032::B::b(int)", "id": "1775727925274471949", "name": "b", "namespace": "", @@ -85,6 +87,7 @@ void tmain(int argc, char **argv) }, { "display_name": "b(double)", + "full_name": "clanguml::t20032::B::b(double)", "id": "404223226092650061", "name": "b", "namespace": "", @@ -98,6 +101,7 @@ void tmain(int argc, char **argv) }, { "display_name": "b(const char *)", + "full_name": "clanguml::t20032::B::b(const char *)", "id": "1676684483397143166", "name": "b", "namespace": "", @@ -111,6 +115,7 @@ void tmain(int argc, char **argv) } ], "display_name": "B", + "full_name": "clanguml::t20032::B", "id": "775765108342558014", "name": "B", "namespace": "clanguml::t20032", @@ -126,6 +131,7 @@ void tmain(int argc, char **argv) "activities": [ { "display_name": "a1(int)", + "full_name": "clanguml::t20032::A::a1(int)", "id": "913842443932719355", "name": "a1", "namespace": "", @@ -139,6 +145,7 @@ void tmain(int argc, char **argv) }, { "display_name": "a2(double)", + "full_name": "clanguml::t20032::A::a2(double)", "id": "1293114170675037977", "name": "a2", "namespace": "", @@ -152,6 +159,7 @@ void tmain(int argc, char **argv) }, { "display_name": "a3(const char *)", + "full_name": "clanguml::t20032::A::a3(const char *)", "id": "2099821524363509275", "name": "a3", "namespace": "", @@ -165,6 +173,7 @@ void tmain(int argc, char **argv) } ], "display_name": "A", + "full_name": "clanguml::t20032::A", "id": "1674177120713592616", "name": "A", "namespace": "clanguml::t20032", diff --git a/docs/test_cases/t20032_sequence.svg b/docs/test_cases/t20032_sequence.svg index e69e3b41..2b8f3b2a 100644 --- a/docs/test_cases/t20032_sequence.svg +++ b/docs/test_cases/t20032_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,47 +9,47 @@ - - - - - - - + + + + + + + - - + + tmain(int,char **) - + tmain(int,char **) - - + + B - + B - - + + A - + A - - - - - - - - + + + + + + + + b(int) - + a1(int) @@ -60,12 +60,12 @@ int - + b(double) - + a2(double) @@ -76,12 +76,12 @@ double - + b(const char *) - + a3(const char *) diff --git a/docs/test_cases/t20033.md b/docs/test_cases/t20033.md index 1c01220c..5eb313af 100644 --- a/docs/test_cases/t20033.md +++ b/docs/test_cases/t20033.md @@ -95,6 +95,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20033::tmain()", "id": "2284981553733959328", "name": "tmain", "namespace": "clanguml::t20033", @@ -110,6 +111,7 @@ int tmain() "activities": [ { "display_name": "a1()", + "full_name": "clanguml::t20033::A::a1()", "id": "558885502745634115", "name": "a1", "namespace": "", @@ -123,6 +125,7 @@ int tmain() }, { "display_name": "a2()", + "full_name": "clanguml::t20033::A::a2()", "id": "748502947476611794", "name": "a2", "namespace": "", @@ -136,6 +139,7 @@ int tmain() }, { "display_name": "a3()", + "full_name": "clanguml::t20033::A::a3()", "id": "55903385814245839", "name": "a3", "namespace": "", @@ -149,6 +153,7 @@ int tmain() }, { "display_name": "a4()", + "full_name": "clanguml::t20033::A::a4()", "id": "1686426476339443579", "name": "a4", "namespace": "", @@ -162,6 +167,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20033::A", "id": "615995652843962691", "name": "A", "namespace": "clanguml::t20033", diff --git a/docs/test_cases/t20033_sequence.svg b/docs/test_cases/t20033_sequence.svg index 889dfc1e..7748f839 100644 --- a/docs/test_cases/t20033_sequence.svg +++ b/docs/test_cases/t20033_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,73 +9,73 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - + + + + + - + - - + + tmain() - + tmain() - - + + A - + A - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + alt [false] [reinterpret_cast<uint64_t>(&a) % 100 == 0ULL] - + a1() @@ -84,7 +84,7 @@ [reinterpret_cast<uint64_t>(&a) % 64 == 0ULL] - + a2() @@ -93,7 +93,7 @@ [a.a2() == 2 && a.a3() == 3] - + [ @@ -102,7 +102,7 @@ - + [ @@ -111,7 +111,7 @@ - + a3() @@ -119,7 +119,7 @@ - + a4() @@ -130,7 +130,7 @@ alt [int i = a.a2(); i != 2] - + [ @@ -139,7 +139,7 @@ - + a3() @@ -150,7 +150,7 @@ loop [int i = 0; i < a.a2(); i++] - + [ @@ -159,14 +159,14 @@ - + a3() - + a3() @@ -177,7 +177,7 @@ loop [retry_count--] - + a2() @@ -188,14 +188,14 @@ loop [retry_count++ < a.a3()] - + a4() - + [ @@ -208,7 +208,7 @@ alt [a.a4() % 6] - + [ @@ -222,7 +222,7 @@ loop [ints] - + a4() diff --git a/docs/test_cases/t20034.md b/docs/test_cases/t20034.md index e840ab54..b31f8c94 100644 --- a/docs/test_cases/t20034.md +++ b/docs/test_cases/t20034.md @@ -103,6 +103,7 @@ void B::b4() "activities": [ { "display_name": "d2()", + "full_name": "clanguml::t20034::D::d2()", "id": "1707514178726476738", "name": "d2", "namespace": "", @@ -116,6 +117,7 @@ void B::b4() } ], "display_name": "D", + "full_name": "clanguml::t20034::D", "id": "272777525372220260", "name": "D", "namespace": "clanguml::t20034", @@ -131,6 +133,7 @@ void B::b4() "activities": [ { "display_name": "c2()", + "full_name": "clanguml::t20034::C::c2()", "id": "472904899982022039", "name": "c2", "namespace": "", @@ -144,6 +147,7 @@ void B::b4() }, { "display_name": "c4()", + "full_name": "clanguml::t20034::C::c4()", "id": "395720534444062628", "name": "c4", "namespace": "", @@ -157,6 +161,7 @@ void B::b4() }, { "display_name": "c1()", + "full_name": "clanguml::t20034::C::c1()", "id": "148530508384958711", "name": "c1", "namespace": "", @@ -170,6 +175,7 @@ void B::b4() }, { "display_name": "c3()", + "full_name": "clanguml::t20034::C::c3()", "id": "2116989777037608337", "name": "c3", "namespace": "", @@ -183,6 +189,7 @@ void B::b4() } ], "display_name": "C", + "full_name": "clanguml::t20034::C", "id": "2153793652884753477", "name": "C", "namespace": "clanguml::t20034", @@ -198,6 +205,7 @@ void B::b4() "activities": [ { "display_name": "b2()", + "full_name": "clanguml::t20034::B::b2()", "id": "1034410188120190919", "name": "b2", "namespace": "", @@ -211,6 +219,7 @@ void B::b4() }, { "display_name": "b4()", + "full_name": "clanguml::t20034::B::b4()", "id": "1774155279072101253", "name": "b4", "namespace": "", @@ -224,6 +233,7 @@ void B::b4() }, { "display_name": "b1()", + "full_name": "clanguml::t20034::B::b1()", "id": "289899516984058785", "name": "b1", "namespace": "", @@ -237,6 +247,7 @@ void B::b4() } ], "display_name": "B", + "full_name": "clanguml::t20034::B", "id": "1214895773389400008", "name": "B", "namespace": "clanguml::t20034", @@ -252,6 +263,7 @@ void B::b4() "activities": [ { "display_name": "a2()", + "full_name": "clanguml::t20034::A::a2()", "id": "1307188853155365430", "name": "a2", "namespace": "", @@ -265,6 +277,7 @@ void B::b4() } ], "display_name": "A", + "full_name": "clanguml::t20034::A", "id": "1029414747563549012", "name": "A", "namespace": "clanguml::t20034", @@ -280,6 +293,7 @@ void B::b4() "activities": [ { "display_name": "operator()() const", + "full_name": "clanguml::t20034::D::d2()::(lambda t20034.cc:56:18)::operator()() const", "id": "1534431449322420953", "name": "operator()", "namespace": "", @@ -287,6 +301,7 @@ void B::b4() } ], "display_name": "D::d2()::(lambda t20034.cc:56:18)", + "full_name": "clanguml::t20034::D::d2()::(lambda t20034.cc:56:18)", "id": "1026588549514900751", "name": "D::d2()::(lambda t20034.cc:56:18)", "namespace": "clanguml::t20034", diff --git a/docs/test_cases/t20034_sequence.svg b/docs/test_cases/t20034_sequence.svg index a0427171..9bc2f7b6 100644 --- a/docs/test_cases/t20034_sequence.svg +++ b/docs/test_cases/t20034_sequence.svg @@ -1,6 +1,6 @@ - + @@ -14,154 +14,154 @@ - - + + D - + D - - + + C - + C - - + + B - + B - - + + A - + A - - + + D::d2()::(lambda t20034.cc:56:18) - + D::d2()::(lambda t20034.cc:56:18) d2() - + c2() - + b2() - + a2() - + d2() - + operator()() const - + a2() - + d2() - + a2() - + d2() - + c4() - + b4() - + b2() - + a2() - + d2() - + c1() - + b1() - + a2() - + d2() - + c3() - + c2() - + b2() - + a2() diff --git a/docs/test_cases/t20035.md b/docs/test_cases/t20035.md index a9d791df..f1ad44a2 100644 --- a/docs/test_cases/t20035.md +++ b/docs/test_cases/t20035.md @@ -44,6 +44,7 @@ int tmain(int argc, char **argv) { return a(argc); } "participants": [ { "display_name": "tmain(int,char **)", + "full_name": "clanguml::t20035::tmain(int,char **)", "id": "1380099746477810520", "name": "tmain", "namespace": "clanguml::t20035", @@ -57,6 +58,7 @@ int tmain(int argc, char **argv) { return a(argc); } }, { "display_name": "a(int)", + "full_name": "clanguml::t20035::a(int)", "id": "1503144831959453736", "name": "a", "namespace": "clanguml::t20035", @@ -70,6 +72,7 @@ int tmain(int argc, char **argv) { return a(argc); } }, { "display_name": "b1(int)", + "full_name": "clanguml::t20035::b1(int)", "id": "440199113909747659", "name": "b1", "namespace": "clanguml::t20035", @@ -83,6 +86,7 @@ int tmain(int argc, char **argv) { return a(argc); } }, { "display_name": "c(int)", + "full_name": "clanguml::t20035::c(int)", "id": "709102392181022891", "name": "c", "namespace": "clanguml::t20035", diff --git a/docs/test_cases/t20035_sequence.svg b/docs/test_cases/t20035_sequence.svg index da4171f7..6ce8d200 100644 --- a/docs/test_cases/t20035_sequence.svg +++ b/docs/test_cases/t20035_sequence.svg @@ -1,6 +1,6 @@ - + @@ -13,39 +13,39 @@ - - + + tmain(int,char **) - + tmain(int,char **) - - + + a(int) - + a(int) - - + + b1(int) - + b1(int) - - + + c(int) - + c(int) - + - + - + diff --git a/docs/test_cases/t20036.md b/docs/test_cases/t20036.md index 9b3e4dae..5f24bb5e 100644 --- a/docs/test_cases/t20036.md +++ b/docs/test_cases/t20036.md @@ -75,6 +75,7 @@ struct D { "activities": [ { "display_name": "c1()", + "full_name": "clanguml::t20036::C::c1()", "id": "1742507735898803374", "name": "c1", "namespace": "", @@ -88,6 +89,7 @@ struct D { }, { "display_name": "c2()", + "full_name": "clanguml::t20036::C::c2()", "id": "128745191811378037", "name": "c2", "namespace": "", @@ -101,6 +103,7 @@ struct D { }, { "display_name": "c4()", + "full_name": "clanguml::t20036::C::c4()", "id": "1735839766717973272", "name": "c4", "namespace": "", @@ -114,6 +117,7 @@ struct D { }, { "display_name": "c3()", + "full_name": "clanguml::t20036::C::c3()", "id": "1523531372012294984", "name": "c3", "namespace": "", @@ -127,6 +131,7 @@ struct D { } ], "display_name": "C", + "full_name": "clanguml::t20036::C", "id": "589458700000736705", "name": "C", "namespace": "clanguml::t20036", @@ -142,6 +147,7 @@ struct D { "activities": [ { "display_name": "b1()", + "full_name": "clanguml::t20036::B::b1()", "id": "203660950902052846", "name": "b1", "namespace": "", @@ -155,6 +161,7 @@ struct D { }, { "display_name": "b2()", + "full_name": "clanguml::t20036::B::b2()", "id": "1726094580455938498", "name": "b2", "namespace": "", @@ -168,6 +175,7 @@ struct D { } ], "display_name": "B", + "full_name": "clanguml::t20036::B", "id": "607147607288902300", "name": "B", "namespace": "clanguml::t20036", @@ -183,6 +191,7 @@ struct D { "activities": [ { "display_name": "a2()", + "full_name": "clanguml::t20036::A::a2()", "id": "2124074228514438863", "name": "a2", "namespace": "", @@ -196,6 +205,7 @@ struct D { } ], "display_name": "A", + "full_name": "clanguml::t20036::A", "id": "399722216848214287", "name": "A", "namespace": "clanguml::t20036", @@ -211,6 +221,7 @@ struct D { "activities": [ { "display_name": "d1()", + "full_name": "clanguml::t20036::D::d1()", "id": "701488875613014930", "name": "d1", "namespace": "", @@ -224,6 +235,7 @@ struct D { }, { "display_name": "d3()", + "full_name": "clanguml::t20036::D::d3()", "id": "1897648539724183065", "name": "d3", "namespace": "", @@ -237,6 +249,7 @@ struct D { }, { "display_name": "d2()", + "full_name": "clanguml::t20036::D::d2()", "id": "1534436779969087203", "name": "d2", "namespace": "", @@ -250,6 +263,7 @@ struct D { } ], "display_name": "D", + "full_name": "clanguml::t20036::D", "id": "847434467114564641", "name": "D", "namespace": "clanguml::t20036", diff --git a/docs/test_cases/t20036_sequence.svg b/docs/test_cases/t20036_sequence.svg index 88d8d36c..bac4d9b4 100644 --- a/docs/test_cases/t20036_sequence.svg +++ b/docs/test_cases/t20036_sequence.svg @@ -1,6 +1,6 @@ - + @@ -13,131 +13,131 @@ - - + + C - + C - - + + B - + B - - + + A - + A - - + + D - + D c1() - + b1() - + a2() - + d1() - + c2() - + b2() - + a2() - + d3() - + a2() - + c4() - + b2() - + a2() - + c3() - + c2() - + b2() - + a2() - + d2() - + c2() - + b2() - + a2() diff --git a/docs/test_cases/t20037.md b/docs/test_cases/t20037.md index 216ef07c..40b13c62 100644 --- a/docs/test_cases/t20037.md +++ b/docs/test_cases/t20037.md @@ -67,6 +67,7 @@ void tmain(int argc, char **argv) "participants": [ { "display_name": "tmain(int,char **)", + "full_name": "clanguml::t20037::tmain(int,char **)", "id": "1676651465274088148", "name": "tmain", "namespace": "clanguml::t20037", @@ -80,6 +81,7 @@ void tmain(int argc, char **argv) }, { "display_name": "a()", + "full_name": "clanguml::t20037::a()", "id": "150460916850164805", "name": "a", "namespace": "clanguml::t20037", @@ -95,6 +97,7 @@ void tmain(int argc, char **argv) "activities": [ { "display_name": "A()", + "full_name": "clanguml::t20037::A::A()", "id": "1135451191676888496", "name": "A", "namespace": "", @@ -108,6 +111,7 @@ void tmain(int argc, char **argv) } ], "display_name": "A", + "full_name": "clanguml::t20037::A", "id": "1329920824155530080", "name": "A", "namespace": "clanguml::t20037", @@ -121,6 +125,7 @@ void tmain(int argc, char **argv) }, { "display_name": "initb()", + "full_name": "clanguml::t20037::initb()", "id": "1303264946914255327", "name": "initb", "namespace": "clanguml::t20037", @@ -136,6 +141,7 @@ void tmain(int argc, char **argv) "activities": [ { "display_name": "get()", + "full_name": "clanguml::t20037::B::get()", "id": "107877908217538137", "name": "get", "namespace": "", @@ -149,6 +155,7 @@ void tmain(int argc, char **argv) } ], "display_name": "B", + "full_name": "clanguml::t20037::B", "id": "1746900845528413124", "name": "B", "namespace": "clanguml::t20037", @@ -162,6 +169,7 @@ void tmain(int argc, char **argv) }, { "display_name": "c()", + "full_name": "clanguml::t20037::c()", "id": "1349992361928784583", "name": "c", "namespace": "clanguml::t20037", @@ -297,6 +305,46 @@ void tmain(int argc, char **argv) }, "type": "message" }, + { + "from": { + "activity_id": "150460916850164805", + "participant_id": "150460916850164805" + }, + "name": "get()", + "return_type": "int", + "scope": "normal", + "source_location": { + "column": 18, + "file": "t20037.cc", + "line": 28, + "translation_unit": "t20037.cc" + }, + "to": { + "activity_id": "107877908217538137", + "participant_id": "1746900845528413124" + }, + "type": "message" + }, + { + "from": { + "activity_id": "150460916850164805", + "participant_id": "150460916850164805" + }, + "name": "", + "return_type": "int", + "scope": "normal", + "source_location": { + "column": 28, + "file": "t20037.cc", + "line": 28, + "translation_unit": "t20037.cc" + }, + "to": { + "activity_id": "1349992361928784583", + "participant_id": "1349992361928784583" + }, + "type": "message" + }, { "from": { "activity_id": "1676651465274088148", @@ -316,6 +364,46 @@ void tmain(int argc, char **argv) "participant_id": "150460916850164805" }, "type": "message" + }, + { + "from": { + "activity_id": "150460916850164805", + "participant_id": "150460916850164805" + }, + "name": "get()", + "return_type": "int", + "scope": "normal", + "source_location": { + "column": 18, + "file": "t20037.cc", + "line": 28, + "translation_unit": "t20037.cc" + }, + "to": { + "activity_id": "107877908217538137", + "participant_id": "1746900845528413124" + }, + "type": "message" + }, + { + "from": { + "activity_id": "150460916850164805", + "participant_id": "150460916850164805" + }, + "name": "", + "return_type": "int", + "scope": "normal", + "source_location": { + "column": 28, + "file": "t20037.cc", + "line": 28, + "translation_unit": "t20037.cc" + }, + "to": { + "activity_id": "1349992361928784583", + "participant_id": "1349992361928784583" + }, + "type": "message" } ], "start_from": { diff --git a/docs/test_cases/t20037_sequence.svg b/docs/test_cases/t20037_sequence.svg index a6e67d5d..924baa49 100644 --- a/docs/test_cases/t20037_sequence.svg +++ b/docs/test_cases/t20037_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,95 +9,95 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - + + tmain(int,char **) - + tmain(int,char **) - - + + a() - + a() - - + + A - + A - - + + initb() - + initb() - - + + B - + B - - + + c() - + c() - - - - - - - - - - - - - + + + + + + + + + + + + + - + A() - + - + get() - + @@ -105,18 +105,18 @@ - + - + get() - + @@ -124,18 +124,18 @@ - + - + get() - + diff --git a/docs/test_cases/t20038.md b/docs/test_cases/t20038.md index babaeeb1..30bc51d2 100644 --- a/docs/test_cases/t20038.md +++ b/docs/test_cases/t20038.md @@ -141,6 +141,7 @@ template T add(T a, T b) "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20038::tmain()", "id": "1013610625329227974", "name": "tmain", "namespace": "clanguml::t20038", @@ -156,6 +157,7 @@ template T add(T a, T b) "activities": [ { "display_name": "b()", + "full_name": "clanguml::t20038::B::b()", "id": "690314603725772987", "name": "b", "namespace": "", @@ -169,6 +171,7 @@ template T add(T a, T b) }, { "display_name": "bbb()", + "full_name": "clanguml::t20038::B::bbb()", "id": "1902331999195245434", "name": "bbb", "namespace": "", @@ -182,6 +185,7 @@ template T add(T a, T b) }, { "display_name": "bbbb()", + "full_name": "clanguml::t20038::B::bbbb()", "id": "57189865474209187", "name": "bbbb", "namespace": "", @@ -195,6 +199,7 @@ template T add(T a, T b) }, { "display_name": "wrap(int)", + "full_name": "clanguml::t20038::B::wrap(int)", "id": "732774941205637034", "name": "wrap", "namespace": "", @@ -208,6 +213,7 @@ template T add(T a, T b) }, { "display_name": "bbbbb()", + "full_name": "clanguml::t20038::B::bbbbb()", "id": "726295067786650864", "name": "bbbbb", "namespace": "", @@ -221,6 +227,7 @@ template T add(T a, T b) } ], "display_name": "B", + "full_name": "clanguml::t20038::B", "id": "1040787777721396414", "name": "B", "namespace": "clanguml::t20038", @@ -236,6 +243,7 @@ template T add(T a, T b) "activities": [ { "display_name": "a()", + "full_name": "clanguml::t20038::A::a()", "id": "1311298747919334371", "name": "a", "namespace": "", @@ -249,6 +257,7 @@ template T add(T a, T b) }, { "display_name": "aaa()", + "full_name": "clanguml::t20038::A::aaa()", "id": "2157208254318041144", "name": "aaa", "namespace": "", @@ -262,6 +271,7 @@ template T add(T a, T b) }, { "display_name": "aaaa()", + "full_name": "clanguml::t20038::A::aaaa()", "id": "1370854824770046153", "name": "aaaa", "namespace": "", @@ -275,6 +285,7 @@ template T add(T a, T b) } ], "display_name": "A", + "full_name": "clanguml::t20038::A", "id": "2022724814881480995", "name": "A", "namespace": "clanguml::t20038", @@ -288,6 +299,7 @@ template T add(T a, T b) }, { "display_name": "add(int,int)", + "full_name": "clanguml::t20038::add(int,int)", "id": "2008308445790932614", "name": "add", "namespace": "clanguml::t20038", @@ -301,6 +313,7 @@ template T add(T a, T b) }, { "display_name": "add_impl(int,int)", + "full_name": "clanguml::t20038::add_impl(int,int)", "id": "1863007445376981099", "name": "add_impl", "namespace": "clanguml::t20038", @@ -314,6 +327,7 @@ template T add(T a, T b) }, { "display_name": "add_impl(double,double)", + "full_name": "clanguml::t20038::add_impl(double,double)", "id": "1722521509166427875", "name": "add_impl", "namespace": "clanguml::t20038", @@ -406,6 +420,26 @@ template T add(T a, T b) "participant_id": "1040787777721396414" }, "type": "message" + }, + { + "from": { + "activity_id": "690314603725772987", + "participant_id": "1040787777721396414" + }, + "name": "a()", + "return_type": "int", + "scope": "normal", + "source_location": { + "column": 22, + "file": "t20038.cc", + "line": 29, + "translation_unit": "t20038.cc" + }, + "to": { + "activity_id": "1311298747919334371", + "participant_id": "2022724814881480995" + }, + "type": "message" } ], "type": "alternative" @@ -617,6 +651,46 @@ template T add(T a, T b) }, "type": "message" }, + { + "from": { + "activity_id": "1370854824770046153", + "participant_id": "2022724814881480995" + }, + "name": "", + "return_type": "", + "scope": "normal", + "source_location": { + "column": 25, + "file": "t20038.cc", + "line": 23, + "translation_unit": "t20038.cc" + }, + "to": { + "activity_id": "2008308445790932614", + "participant_id": "2008308445790932614" + }, + "type": "message" + }, + { + "from": { + "activity_id": "2008308445790932614", + "participant_id": "2008308445790932614" + }, + "name": "", + "return_type": "", + "scope": "normal", + "source_location": { + "column": 12, + "file": "include/t20038.h", + "line": 11, + "translation_unit": "t20038.cc" + }, + "to": { + "activity_id": "1863007445376981099", + "participant_id": "1863007445376981099" + }, + "type": "message" + }, { "activity_id": "1013610625329227974", "branches": [ @@ -642,6 +716,26 @@ template T add(T a, T b) "participant_id": "1040787777721396414" }, "type": "message" + }, + { + "from": { + "activity_id": "1902331999195245434", + "participant_id": "1040787777721396414" + }, + "name": "aaa()", + "return_type": "int", + "scope": "normal", + "source_location": { + "column": 24, + "file": "t20038.cc", + "line": 33, + "translation_unit": "t20038.cc" + }, + "to": { + "activity_id": "2157208254318041144", + "participant_id": "2022724814881480995" + }, + "type": "message" } ], "type": "consequent" diff --git a/docs/test_cases/t20038_sequence.svg b/docs/test_cases/t20038_sequence.svg index 41c9fa0f..914de531 100644 --- a/docs/test_cases/t20038_sequence.svg +++ b/docs/test_cases/t20038_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,29 +9,29 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + @@ -39,62 +39,62 @@ - - + + tmain() - + tmain() - - + + B - + B - - + + A - + A - - + + add<int>(int,int) - + add<int>(int,int) - - + + add_impl<int>(int,int) - + add_impl<int>(int,int) - - + + add_impl<double>(double,double) - + add_impl<double>(double,double) - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + Nisl purus in mollis nunc sed id semper. Varius vel pharetra vel turpis. Arcu @@ -111,18 +111,18 @@ alt - + Repeat 5 times... loop - + b() - + a() @@ -132,15 +132,15 @@ - + ... or just once - + b() - + a() @@ -149,12 +149,12 @@ - + bbb() - + aaa() @@ -163,21 +163,21 @@ - + bbbb() - + aaaa() - + - + @@ -189,44 +189,44 @@ - + This comment should be rendered only once - + wrap(int) - + What is 2 + 2? - + - + Calling B::bbbbb() - + bbbbb() - + aaaa() - + - + @@ -238,23 +238,23 @@ - + This is a conditional operator alt - + This is a conditional operator - + [ bbb() ] - + aaa() diff --git a/docs/test_cases/t20039.md b/docs/test_cases/t20039.md index 14b0b4ef..a6b9e2a4 100644 --- a/docs/test_cases/t20039.md +++ b/docs/test_cases/t20039.md @@ -72,6 +72,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20039::tmain()", "id": "2148451609276010605", "name": "tmain", "namespace": "clanguml::t20039", @@ -87,6 +88,7 @@ int tmain() "activities": [ { "display_name": "run()", + "full_name": "clanguml::t20039::R::run()", "id": "743095879760855186", "name": "run", "namespace": "", @@ -100,6 +102,7 @@ int tmain() } ], "display_name": "R", + "full_name": "clanguml::t20039::R", "id": "911510236910860394", "name": "R", "namespace": "clanguml::t20039", @@ -115,6 +118,7 @@ int tmain() "activities": [ { "display_name": "a(int)", + "full_name": "clanguml::t20039::A::a(int)", "id": "1669283381205253105", "name": "a", "namespace": "", @@ -128,6 +132,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20039::A", "id": "1909240382008619079", "name": "A", "namespace": "clanguml::t20039", @@ -143,6 +148,7 @@ int tmain() "activities": [ { "display_name": "a(int_vec_t)", + "full_name": "clanguml::t20039::A::a(int_vec_t)", "id": "102043386959871430", "name": "a", "namespace": "", @@ -156,6 +162,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20039::A", "id": "2044714081517303079", "name": "A", "namespace": "clanguml::t20039", @@ -171,6 +178,7 @@ int tmain() "activities": [ { "display_name": "a(string_vec_t)", + "full_name": "clanguml::t20039::A::a(string_vec_t)", "id": "877375915521239216", "name": "a", "namespace": "", @@ -184,6 +192,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20039::A", "id": "985421674263139595", "name": "A", "namespace": "clanguml::t20039", @@ -199,6 +208,7 @@ int tmain() "activities": [ { "display_name": "a(int_map_t)", + "full_name": "clanguml::t20039::A::a(int_map_t)", "id": "720393008985738554", "name": "a", "namespace": "", @@ -212,6 +222,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20039::A", "id": "1577435969137543418", "name": "A", "namespace": "clanguml::t20039", @@ -227,6 +238,7 @@ int tmain() "activities": [ { "display_name": "a(string_map_t)", + "full_name": "clanguml::t20039::A::a(string_map_t)", "id": "1228686762653429102", "name": "a", "namespace": "", @@ -240,6 +252,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20039::A", "id": "1410668113085504962", "name": "A", "namespace": "clanguml::t20039", @@ -281,7 +294,7 @@ int tmain() "participant_id": "911510236910860394" }, "name": "a(int)", - "return_type": "std::vector>", + "return_type": "std::vector", "scope": "normal", "source_location": { "column": 9, diff --git a/docs/test_cases/t20039_sequence.svg b/docs/test_cases/t20039_sequence.svg index 499d2998..7f419259 100644 --- a/docs/test_cases/t20039_sequence.svg +++ b/docs/test_cases/t20039_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,13 +9,13 @@ - - - - - - - + + + + + + + @@ -23,89 +23,89 @@ - - + + tmain() - + tmain() - - + + R - + R - - + + A<int> - + A<int> - - + + A<int_vec_t> - + A<int_vec_t> - - + + A<string_vec_t> - + A<string_vec_t> - - + + A<int_map_t> - + A<int_map_t> - - + + A<string_map_t> - + A<string_map_t> - - - - - - - - + + + + + + + + run() - + a(int) - + a(int_vec_t) - + a(string_vec_t) - + a(int_map_t) - + a(string_map_t) diff --git a/docs/test_cases/t20040.md b/docs/test_cases/t20040.md index 2dadfaaf..65ed54af 100644 --- a/docs/test_cases/t20040.md +++ b/docs/test_cases/t20040.md @@ -57,6 +57,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20040::tmain()", "id": "998622560147459663", "name": "tmain", "namespace": "clanguml::t20040", @@ -69,7 +70,8 @@ void tmain() "type": "function" }, { - "display_name": "print(int,double,std::basic_string)", + "display_name": "print(int,double,std::string)", + "full_name": "clanguml::t20040::print(int,double,std::basic_string)", "id": "466846361794024298", "name": "print", "namespace": "clanguml::t20040", @@ -82,7 +84,8 @@ void tmain() "type": "function_template" }, { - "display_name": "print(double,std::basic_string)", + "display_name": "print(double,std::string)", + "full_name": "clanguml::t20040::print(double,std::basic_string)", "id": "1387681712381484036", "name": "print", "namespace": "clanguml::t20040", @@ -95,7 +98,8 @@ void tmain() "type": "function_template" }, { - "display_name": "print(std::basic_string)", + "display_name": "print(std::string)", + "full_name": "clanguml::t20040::print(std::basic_string)", "id": "1353926867284821849", "name": "print", "namespace": "clanguml::t20040", @@ -109,6 +113,7 @@ void tmain() }, { "display_name": "print()", + "full_name": "clanguml::t20040::print()", "id": "245418438894072749", "name": "print", "namespace": "clanguml::t20040", @@ -121,7 +126,8 @@ void tmain() "type": "function" }, { - "display_name": "doublePrint(std::basic_string,int)", + "display_name": "doublePrint(std::string,int)", + "full_name": "clanguml::t20040::doublePrint(std::basic_string,int)", "id": "2024126405552345351", "name": "doublePrint", "namespace": "clanguml::t20040", @@ -134,7 +140,8 @@ void tmain() "type": "function_template" }, { - "display_name": "print(std::basic_string,int)", + "display_name": "print(std::string,int)", + "full_name": "clanguml::t20040::print(std::basic_string,int)", "id": "1349996183789322606", "name": "print", "namespace": "clanguml::t20040", @@ -148,6 +155,7 @@ void tmain() }, { "display_name": "print(int)", + "full_name": "clanguml::t20040::print(int)", "id": "1189427464789523930", "name": "print", "namespace": "clanguml::t20040", diff --git a/docs/test_cases/t20040_sequence.svg b/docs/test_cases/t20040_sequence.svg index d19c8a2c..501a7eac 100644 --- a/docs/test_cases/t20040_sequence.svg +++ b/docs/test_cases/t20040_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,15 +9,15 @@ - - - - - - - - - + + + + + + + + + @@ -26,92 +26,92 @@ - - + + tmain() - + tmain() - - + + print<int,double,std::string>(int,double,std::string) - + print<int,double,std::string>(int,double,std::string) - - + + print<double,std::string>(double,std::string) - + print<double,std::string>(double,std::string) - - + + print<std::string>(std::string) - + print<std::string>(std::string) - - + + print() - + print() - - + + doublePrint<std::string,int>(std::string,int) - + doublePrint<std::string,int>(std::string,int) - - + + print<std::string,int>(std::string,int) - + print<std::string,int>(std::string,int) - - + + print<int>(int) - + print<int>(int) - - - - - - - - - - + + + + + + + + + + - + - + - + - + - + - + - + diff --git a/docs/test_cases/t20041.md b/docs/test_cases/t20041.md index 2a504842..a1a81c1e 100644 --- a/docs/test_cases/t20041.md +++ b/docs/test_cases/t20041.md @@ -60,6 +60,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20041::tmain()", "id": "1389566400082670258", "name": "tmain", "namespace": "clanguml::t20041", @@ -75,6 +76,7 @@ void tmain() "activities": [ { "display_name": "print(int,double,std::string)", + "full_name": "clanguml::t20041::A::print(int,double,std::string)", "id": "532000038063429229", "name": "print", "namespace": "", @@ -88,6 +90,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20041::A", "id": "832678750316145968", "name": "A", "namespace": "clanguml::t20041", @@ -103,6 +106,7 @@ void tmain() "activities": [ { "display_name": "print(double,std::string)", + "full_name": "clanguml::t20041::A::print(double,std::string)", "id": "1403962403457522629", "name": "print", "namespace": "", @@ -116,6 +120,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20041::A", "id": "942399465509044163", "name": "A", "namespace": "clanguml::t20041", @@ -131,6 +136,7 @@ void tmain() "activities": [ { "display_name": "print(std::string)", + "full_name": "clanguml::t20041::A::print(std::string)", "id": "1658479415048358058", "name": "print", "namespace": "", @@ -144,6 +150,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20041::A", "id": "1390965848075226081", "name": "A", "namespace": "clanguml::t20041", @@ -159,6 +166,7 @@ void tmain() "activities": [ { "display_name": "print()", + "full_name": "clanguml::t20041::A::print()", "id": "1295142493768214222", "name": "print", "namespace": "", @@ -172,6 +180,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20041::A", "id": "1052108783247143031", "name": "A", "namespace": "clanguml::t20041", diff --git a/docs/test_cases/t20041_sequence.svg b/docs/test_cases/t20041_sequence.svg index 080eab86..1cd7b267 100644 --- a/docs/test_cases/t20041_sequence.svg +++ b/docs/test_cases/t20041_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,67 +9,67 @@ - - - - - + + + + + - - + + tmain() - + tmain() - - + + A<int,double,std::string> - + A<int,double,std::string> - - + + A<double,std::string> - + A<double,std::string> - - + + A<std::string> - + A<std::string> - - + + A - + A - - - - - - + + + + + + print(int,double,std::string) - + print(double,std::string) - + print(std::string) - + print() diff --git a/docs/test_cases/t20042.md b/docs/test_cases/t20042.md index 6c5136af..3ee6b46f 100644 --- a/docs/test_cases/t20042.md +++ b/docs/test_cases/t20042.md @@ -59,6 +59,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20042::tmain()", "id": "609011973422503266", "name": "tmain", "namespace": "clanguml::t20042", @@ -74,6 +75,7 @@ void tmain() "activities": [ { "display_name": "operator()(A &) const", + "full_name": "clanguml::t20042::AHandler::operator()(A &) const", "id": "1803150869170812951", "name": "operator()", "namespace": "", @@ -87,6 +89,7 @@ void tmain() }, { "display_name": "handle(A &) const", + "full_name": "clanguml::t20042::AHandler::handle(A &) const", "id": "505918958102707204", "name": "handle", "namespace": "", @@ -100,6 +103,7 @@ void tmain() } ], "display_name": "AHandler", + "full_name": "clanguml::t20042::AHandler", "id": "169029708750481998", "name": "AHandler", "namespace": "clanguml::t20042", @@ -115,6 +119,7 @@ void tmain() "activities": [ { "display_name": "operator()(B &) const", + "full_name": "clanguml::t20042::BHandler::operator()(B &) const", "id": "1635511505447928279", "name": "operator()", "namespace": "", @@ -128,6 +133,7 @@ void tmain() }, { "display_name": "handle(B &) const", + "full_name": "clanguml::t20042::BHandler::handle(B &) const", "id": "869419286648646110", "name": "handle", "namespace": "", @@ -141,6 +147,7 @@ void tmain() } ], "display_name": "BHandler", + "full_name": "clanguml::t20042::BHandler", "id": "1969158228859108037", "name": "BHandler", "namespace": "clanguml::t20042", diff --git a/docs/test_cases/t20042_sequence.svg b/docs/test_cases/t20042_sequence.svg index c8647f61..d4c9fbe9 100644 --- a/docs/test_cases/t20042_sequence.svg +++ b/docs/test_cases/t20042_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,55 +9,55 @@ - - - - - + + + + + - - + + tmain() - + tmain() - - + + AHandler - + AHandler - - + + BHandler - + BHandler - - - - - - + + + + + + operator()(A &) const - + handle(A &) const - + operator()(B &) const - + diff --git a/docs/test_cases/t20043.md b/docs/test_cases/t20043.md index 3c780e31..6c420471 100644 --- a/docs/test_cases/t20043.md +++ b/docs/test_cases/t20043.md @@ -83,6 +83,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20043::tmain()", "id": "1396184337601679046", "name": "tmain", "namespace": "clanguml::t20043", @@ -98,6 +99,7 @@ int tmain() "activities": [ { "display_name": "d()", + "full_name": "clanguml::t20043::D::d()", "id": "60379393461478854", "name": "d", "namespace": "", @@ -111,6 +113,7 @@ int tmain() } ], "display_name": "D", + "full_name": "clanguml::t20043::D", "id": "1632049250551188852", "name": "D", "namespace": "clanguml::t20043", @@ -126,6 +129,7 @@ int tmain() "activities": [ { "display_name": "c()", + "full_name": "clanguml::t20043::C::c()", "id": "998868776840486830", "name": "c", "namespace": "", @@ -139,6 +143,7 @@ int tmain() } ], "display_name": "C", + "full_name": "clanguml::t20043::C", "id": "605388621050971304", "name": "C", "namespace": "clanguml::t20043", diff --git a/docs/test_cases/t20043_sequence.svg b/docs/test_cases/t20043_sequence.svg index d11e50c6..8aa24f56 100644 --- a/docs/test_cases/t20043_sequence.svg +++ b/docs/test_cases/t20043_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,39 +9,39 @@ - - - + + + - - + + tmain() - + tmain() - - + + D - + D - - + + C - + C - - - - + + + + d() - + c() diff --git a/docs/test_cases/t20044.md b/docs/test_cases/t20044.md index ef55e192..4a7d6d5b 100644 --- a/docs/test_cases/t20044.md +++ b/docs/test_cases/t20044.md @@ -9,7 +9,7 @@ diagrams: glob: - t20044.cc type_aliases: - "detail::expected": result_t + "clanguml::t20044::detail::expected": result_t generate_message_comments: true include: namespaces: @@ -137,6 +137,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20044::tmain()", "id": "252888248193934644", "name": "tmain", "namespace": "clanguml::t20044", @@ -152,6 +153,7 @@ int tmain() "activities": [ { "display_name": "R((lambda at t20044.cc:74:9) &&)", + "full_name": "clanguml::t20044::R::R((lambda at t20044.cc:74:9) &&)", "id": "2121949343931231437", "name": "R", "namespace": "", @@ -165,6 +167,7 @@ int tmain() } ], "display_name": "R", + "full_name": "clanguml::t20044::R", "id": "1556111147598935846", "name": "R", "namespace": "clanguml::t20044", @@ -180,6 +183,7 @@ int tmain() "activities": [ { "display_name": "operator()() const", + "full_name": "clanguml::t20044::tmain()::(lambda t20044.cc:74:9)::operator()() const", "id": "818357152220364831", "name": "operator()", "namespace": "", @@ -187,6 +191,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20044.cc:74:9)", + "full_name": "clanguml::t20044::tmain()::(lambda t20044.cc:74:9)", "id": "731168008522991712", "name": "tmain()::(lambda t20044.cc:74:9)", "namespace": "clanguml::t20044", @@ -202,6 +207,7 @@ int tmain() "activities": [ { "display_name": "a() const", + "full_name": "clanguml::t20044::A::a() const", "id": "853950074322224524", "name": "a", "namespace": "", @@ -215,6 +221,7 @@ int tmain() }, { "display_name": "a5()", + "full_name": "clanguml::t20044::A::a5()", "id": "1743691164520385657", "name": "a5", "namespace": "", @@ -228,6 +235,7 @@ int tmain() }, { "display_name": "a1() const", + "full_name": "clanguml::t20044::A::a1() const", "id": "701399225037526851", "name": "a1", "namespace": "", @@ -241,6 +249,7 @@ int tmain() }, { "display_name": "a2(int) const", + "full_name": "clanguml::t20044::A::a2(int) const", "id": "85144570008244024", "name": "a2", "namespace": "", @@ -254,6 +263,7 @@ int tmain() } ], "display_name": "A", + "full_name": "clanguml::t20044::A", "id": "1026615617828083132", "name": "A", "namespace": "clanguml::t20044", @@ -269,6 +279,7 @@ int tmain() "activities": [ { "display_name": "operator()() const", + "full_name": "clanguml::t20044::tmain()::(lambda t20044.cc:84:18)::operator()() const", "id": "436096372302626180", "name": "operator()", "namespace": "", @@ -276,6 +287,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20044.cc:84:18)", + "full_name": "clanguml::t20044::tmain()::(lambda t20044.cc:84:18)", "id": "1462639563075674191", "name": "tmain()::(lambda t20044.cc:84:18)", "namespace": "clanguml::t20044", @@ -291,6 +303,7 @@ int tmain() "activities": [ { "display_name": "expected(int)", + "full_name": "clanguml::t20044::detail::expected::expected(int)", "id": "1539466150622485129", "name": "expected", "namespace": "", @@ -304,6 +317,7 @@ int tmain() }, { "display_name": "and_then((lambda at t20044.cc:90:19) &&)", + "full_name": "clanguml::t20044::detail::expected::and_then((lambda at t20044.cc:90:19) &&)", "id": "377073498530267347", "name": "and_then", "namespace": "", @@ -316,8 +330,9 @@ int tmain() "type": "method" }, { - "display_name": "and_then(detail::expected (&)(int))", - "id": "688251630893467966", + "display_name": "and_then(result_t (&)(int))", + "full_name": "clanguml::t20044::detail::expected::and_then(result_t (&)(int))", + "id": "1974891758151777473", "name": "and_then", "namespace": "", "source_location": { @@ -329,8 +344,9 @@ int tmain() "type": "method" }, { - "display_name": "and_then(std::function (int)> &)", - "id": "139031379616853201", + "display_name": "and_then(std::function &)", + "full_name": "clanguml::t20044::detail::expected::and_then(std::function &)", + "id": "1228620055083656606", "name": "and_then", "namespace": "", "source_location": { @@ -343,6 +359,7 @@ int tmain() }, { "display_name": "value() const", + "full_name": "clanguml::t20044::detail::expected::value() const", "id": "954804726969205606", "name": "value", "namespace": "", @@ -355,7 +372,8 @@ int tmain() "type": "method" } ], - "display_name": "expected", + "display_name": "result_t", + "full_name": "clanguml::t20044::detail::expected", "id": "109801426773060225", "name": "expected", "namespace": "clanguml::t20044::detail", @@ -371,6 +389,7 @@ int tmain() "activities": [ { "display_name": "operator()(auto &&) const", + "full_name": "clanguml::t20044::tmain()::(lambda t20044.cc:90:19)::operator()(auto &&) const", "id": "1768106129901104346", "name": "operator()", "namespace": "", @@ -378,6 +397,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20044.cc:90:19)", + "full_name": "clanguml::t20044::tmain()::(lambda t20044.cc:90:19)", "id": "929315761786829928", "name": "tmain()::(lambda t20044.cc:90:19)", "namespace": "clanguml::t20044", @@ -541,7 +561,7 @@ int tmain() "participant_id": "252888248193934644" }, "name": "and_then((lambda at t20044.cc:90:19) &&)", - "return_type": "clanguml::t20044::detail::expected", + "return_type": "result_t", "scope": "normal", "source_location": { "column": 12, @@ -634,7 +654,7 @@ int tmain() "participant_id": "252888248193934644" }, "name": "and_then(result_t (&)(int))", - "return_type": "clanguml::t20044::detail::expected", + "return_type": "result_t", "scope": "normal", "source_location": { "column": 12, @@ -643,7 +663,7 @@ int tmain() "translation_unit": "t20044.cc" }, "to": { - "activity_id": "688251630893467966", + "activity_id": "1974891758151777473", "participant_id": "109801426773060225" }, "type": "message" @@ -654,7 +674,7 @@ int tmain() "participant_id": "252888248193934644" }, "name": "and_then(std::function &)", - "return_type": "clanguml::t20044::detail::expected", + "return_type": "result_t", "scope": "normal", "source_location": { "column": 12, @@ -663,7 +683,7 @@ int tmain() "translation_unit": "t20044.cc" }, "to": { - "activity_id": "139031379616853201", + "activity_id": "1228620055083656606", "participant_id": "109801426773060225" }, "type": "message" diff --git a/docs/test_cases/t20044_sequence.svg b/docs/test_cases/t20044_sequence.svg index ae19da59..4b3a8cf5 100644 --- a/docs/test_cases/t20044_sequence.svg +++ b/docs/test_cases/t20044_sequence.svg @@ -1,6 +1,6 @@ - + - + @@ -9,112 +9,112 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - + + + + tmain() - + tmain() - - + + R - + R - - + + tmain()::(lambda t20044.cc:74:9) - + tmain()::(lambda t20044.cc:74:9) - - + + A - + A - - + + tmain()::(lambda t20044.cc:84:18) - + tmain()::(lambda t20044.cc:84:18) - - - detail::expected<int,error> - - detail::expected<int,error> + + + result_t + + result_t - - - tmain()::(lambda t20044.cc:90:19) - - tmain()::(lambda t20044.cc:90:19) + + + tmain()::(lambda t20044.cc:90:19) + + tmain()::(lambda t20044.cc:90:19) - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + R((lambda at t20044.cc:74:9) &&) - + operator()() const - + Call to template constructor with callable parameter and lambda expression as argument - + a() const - + operator()() const - + The message to detail2::run() is skipped due to exclude @@ -123,79 +123,79 @@ rendered TODO: Add some marker to highlight that this is not a direct call - + a5() - + a1() const - - - + + + expected(int) - - - + + + and_then((lambda at t20044.cc:90:19) &&) - + alt - - - - operator()(auto &&) const + + + + operator()(auto &&) const - - - Call to a template method - accepting a callable with - lambda expression as argument, - fully tracked showing method's - activity and - + + + Call to a template method + accepting a callable with + lambda expression as argument, + fully tracked showing method's + activity and + - + a2(int) const - - - + + + expected(int) - - - - + + + + - - - - + + + + and_then(result_t (&)(int)) - - - - + + + + and_then(std::function<result_t (int)> &) - - - - + + + + value() const - + diff --git a/docs/test_cases/t20044_sequence_mermaid.svg b/docs/test_cases/t20044_sequence_mermaid.svg index 03e4df3e..8b2860fa 100644 --- a/docs/test_cases/t20044_sequence_mermaid.svg +++ b/docs/test_cases/t20044_sequence_mermaid.svg @@ -1,14 +1,14 @@ - + - - - tmain()::(lambda t20044.cc:90:19) + + + tmain()::(lambda t20044.cc:90:19) - - - detail::expected<int,error> + + + result_t @@ -42,20 +42,20 @@ - + - - - tmain()::(lambda t20044.cc:90:19) + + + tmain()::(lambda t20044.cc:90:19) - + - - - detail::expected<int,error> + + + result_t @@ -200,57 +200,57 @@ - + - + - + - - - Call to a template method + + + Call to a template method - - accepting a callable with + + accepting a callable with - - lambda expression as argument, + + lambda expression as argument, - - fully tracked showing method's + + fully tracked showing method's - - activity and + + activity and - + - - - + + + alt - - ​ + + ​ - + - + - + R((lambda at t20044.cc:74:9) &&) @@ -264,34 +264,34 @@ a1() const - expected(int) - + expected(int) + ​ - and_then((lambda at t20044.cc:90:19) &&) - - operator()(auto &&) const - - a2(int) const - - expected(int) - - ​ - - ​ - - ​ - - and_then(result_t (&)(int)) - - ​ - - and_then(std::function<result_t (int)> &) - - ​ - - value() const - - ​ - + and_then((lambda at t20044.cc:90:19) &&) + + operator()(auto &&) const + + a2(int) const + + expected(int) + + ​ + + ​ + + ​ + + and_then(result_t (&)(int)) + + ​ + + and_then(std::function<result_t (int)> &) + + ​ + + value() const + + ​ + diff --git a/docs/test_cases/t20045.md b/docs/test_cases/t20045.md index 2b17fa49..9941a857 100644 --- a/docs/test_cases/t20045.md +++ b/docs/test_cases/t20045.md @@ -78,6 +78,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20045::tmain()", "id": "2117440102058621189", "name": "tmain", "namespace": "clanguml::t20045", @@ -91,6 +92,7 @@ int tmain() }, { "display_name": "a2(int)", + "full_name": "clanguml::t20045::a2(int)", "id": "422137031007650421", "name": "a2", "namespace": "clanguml::t20045", @@ -103,7 +105,8 @@ int tmain() "type": "function" }, { - "display_name": "a1<(lambda at t20045.cc:35:18)>((lambda at /home/bartek/devel/clang-uml/tests/t20045/t20045.cc:35:18) &&)", + "display_name": "a1<(lambda at t20045.cc:35:18)>((lambda at t20045.cc:35:18) &&)", + "full_name": "clanguml::t20045::a1<(lambda at t20045.cc:35:18)>((lambda at /home/bartek/devel/clang-uml/tests/t20045/t20045.cc:35:18) &&)", "id": "771242326042389239", "name": "a1", "namespace": "clanguml::t20045", @@ -119,6 +122,7 @@ int tmain() "activities": [ { "display_name": "operator()(auto &&) const", + "full_name": "clanguml::t20045::tmain()::(lambda t20045.cc:35:18)::operator()(auto &&) const", "id": "1420491111902448188", "name": "operator()", "namespace": "", @@ -126,6 +130,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20045.cc:35:18)", + "full_name": "clanguml::t20045::tmain()::(lambda t20045.cc:35:18)", "id": "36644484176793235", "name": "tmain()::(lambda t20045.cc:35:18)", "namespace": "clanguml::t20045", @@ -139,6 +144,7 @@ int tmain() }, { "display_name": "a3(int)", + "full_name": "clanguml::t20045::a3(int)", "id": "399307921304660486", "name": "a3", "namespace": "clanguml::t20045", @@ -151,7 +157,8 @@ int tmain() "type": "function" }, { - "display_name": "a1<(lambda at t20045.cc:37:18)>((lambda at /home/bartek/devel/clang-uml/tests/t20045/t20045.cc:37:18) &&)", + "display_name": "a1<(lambda at t20045.cc:37:18)>((lambda at t20045.cc:37:18) &&)", + "full_name": "clanguml::t20045::a1<(lambda at t20045.cc:37:18)>((lambda at /home/bartek/devel/clang-uml/tests/t20045/t20045.cc:37:18) &&)", "id": "708264873048728082", "name": "a1", "namespace": "clanguml::t20045", @@ -167,6 +174,7 @@ int tmain() "activities": [ { "display_name": "operator()(auto &&) const", + "full_name": "clanguml::t20045::tmain()::(lambda t20045.cc:37:18)::operator()(auto &&) const", "id": "1995217387134011144", "name": "operator()", "namespace": "", @@ -174,6 +182,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20045.cc:37:18)", + "full_name": "clanguml::t20045::tmain()::(lambda t20045.cc:37:18)", "id": "1556269922572504148", "name": "tmain()::(lambda t20045.cc:37:18)", "namespace": "clanguml::t20045", @@ -189,6 +198,7 @@ int tmain() "activities": [ { "display_name": "b1(int)", + "full_name": "clanguml::t20045::B::b1(int)", "id": "820437645998690739", "name": "b1", "namespace": "", @@ -202,6 +212,7 @@ int tmain() } ], "display_name": "B", + "full_name": "clanguml::t20045::B", "id": "1737887355752592935", "name": "B", "namespace": "clanguml::t20045", @@ -214,7 +225,8 @@ int tmain() "type": "class" }, { - "display_name": "a1<(lambda at t20045.cc:39:18)>((lambda at /home/bartek/devel/clang-uml/tests/t20045/t20045.cc:39:18) &&)", + "display_name": "a1<(lambda at t20045.cc:39:18)>((lambda at t20045.cc:39:18) &&)", + "full_name": "clanguml::t20045::a1<(lambda at t20045.cc:39:18)>((lambda at /home/bartek/devel/clang-uml/tests/t20045/t20045.cc:39:18) &&)", "id": "1935046237572139126", "name": "a1", "namespace": "clanguml::t20045", @@ -230,6 +242,7 @@ int tmain() "activities": [ { "display_name": "operator()(auto &&) const", + "full_name": "clanguml::t20045::tmain()::(lambda t20045.cc:39:18)::operator()(auto &&) const", "id": "786866346046560964", "name": "operator()", "namespace": "", @@ -237,6 +250,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20045.cc:39:18)", + "full_name": "clanguml::t20045::tmain()::(lambda t20045.cc:39:18)", "id": "132403781431240789", "name": "tmain()::(lambda t20045.cc:39:18)", "namespace": "clanguml::t20045", @@ -252,6 +266,7 @@ int tmain() "activities": [ { "display_name": "get_x() const", + "full_name": "clanguml::t20045::C::get_x() const", "id": "570815384165305751", "name": "get_x", "namespace": "", @@ -265,6 +280,7 @@ int tmain() } ], "display_name": "C", + "full_name": "clanguml::t20045::C", "id": "1812199014066862625", "name": "C", "namespace": "clanguml::t20045", diff --git a/docs/test_cases/t20045_sequence.svg b/docs/test_cases/t20045_sequence.svg index 4031c6ff..da0266ed 100644 --- a/docs/test_cases/t20045_sequence.svg +++ b/docs/test_cases/t20045_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,17 +9,17 @@ - - - - - - - - - - - + + + + + + + + + + + @@ -31,99 +31,99 @@ - - + + tmain() - + tmain() - - + + a2(int) - + a2(int) - - + + a1<(lambda at t20045.cc:35:18)>((lambda at t20045.cc:35:18) &&) - + a1<(lambda at t20045.cc:35:18)>((lambda at t20045.cc:35:18) &&) - - + + tmain()::(lambda t20045.cc:35:18) - + tmain()::(lambda t20045.cc:35:18) - - + + a3(int) - + a3(int) - - + + a1<(lambda at t20045.cc:37:18)>((lambda at t20045.cc:37:18) &&) - + a1<(lambda at t20045.cc:37:18)>((lambda at t20045.cc:37:18) &&) - - + + tmain()::(lambda t20045.cc:37:18) - + tmain()::(lambda t20045.cc:37:18) - - + + B - + B - - + + a1<(lambda at t20045.cc:39:18)>((lambda at t20045.cc:39:18) &&) - + a1<(lambda at t20045.cc:39:18)>((lambda at t20045.cc:39:18) &&) - - + + tmain()::(lambda t20045.cc:39:18) - + tmain()::(lambda t20045.cc:39:18) - - + + C - + C - - - - - - - - - - - - + + + + + + + + + + + + - + - + operator()(auto &&) const - + @@ -133,16 +133,16 @@ - + - + operator()(auto &&) const - + b1(int) @@ -153,16 +153,16 @@ - + - + operator()(auto &&) const - + get_x() const diff --git a/docs/test_cases/t20046.md b/docs/test_cases/t20046.md index a0e40e1f..1ca17487 100644 --- a/docs/test_cases/t20046.md +++ b/docs/test_cases/t20046.md @@ -55,6 +55,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20046::tmain()", "id": "1092597347191364515", "name": "tmain", "namespace": "clanguml::t20046", @@ -70,6 +71,7 @@ int tmain() "activities": [ { "display_name": "operator()(auto &&) const", + "full_name": "clanguml::t20046::tmain()::(lambda t20046.cc:13:15)::operator()(auto &&) const", "id": "174997669781821772", "name": "operator()", "namespace": "", @@ -77,6 +79,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20046.cc:13:15)", + "full_name": "clanguml::t20046::tmain()::(lambda t20046.cc:13:15)", "id": "1868201491114557068", "name": "tmain()::(lambda t20046.cc:13:15)", "namespace": "clanguml::t20046", @@ -92,6 +95,7 @@ int tmain() "activities": [ { "display_name": "operator()(auto &&) const", + "full_name": "clanguml::t20046::clanguml::t20046::tmain()::(lambda t20046.cc:13:15)::(lambda t20046.cc:14:16)::operator()(auto &&) const", "id": "771372907204554082", "name": "operator()", "namespace": "", @@ -99,6 +103,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20046.cc:13:15)::(lambda t20046.cc:14:16)", + "full_name": "clanguml::t20046::clanguml::t20046::tmain()::(lambda t20046.cc:13:15)::(lambda t20046.cc:14:16)", "id": "163480314503646451", "name": "clanguml::t20046::tmain()::(lambda t20046.cc:13:15)::(lambda t20046.cc:14:16)", "namespace": "clanguml::t20046", @@ -112,6 +117,7 @@ int tmain() }, { "display_name": "a2(int)", + "full_name": "clanguml::t20046::a2(int)", "id": "267222823829967475", "name": "a2", "namespace": "clanguml::t20046", @@ -124,7 +130,8 @@ int tmain() "type": "function" }, { - "display_name": "a1<(lambda at t20046.cc:19:9)>((lambda at /home/bartek/devel/clang-uml/tests/t20046/t20046.cc:19:9) &&)", + "display_name": "a1<(lambda at t20046.cc:19:9)>((lambda at t20046.cc:19:9) &&)", + "full_name": "clanguml::t20046::a1<(lambda at t20046.cc:19:9)>((lambda at /home/bartek/devel/clang-uml/tests/t20046/t20046.cc:19:9) &&)", "id": "404852580994337987", "name": "a1", "namespace": "clanguml::t20046", @@ -140,6 +147,7 @@ int tmain() "activities": [ { "display_name": "operator()(auto &&) const", + "full_name": "clanguml::t20046::tmain()::(lambda t20046.cc:19:9)::operator()(auto &&) const", "id": "326496579896748789", "name": "operator()", "namespace": "", @@ -147,6 +155,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20046.cc:19:9)", + "full_name": "clanguml::t20046::tmain()::(lambda t20046.cc:19:9)", "id": "1833526997995356163", "name": "tmain()::(lambda t20046.cc:19:9)", "namespace": "clanguml::t20046", @@ -162,6 +171,7 @@ int tmain() "activities": [ { "display_name": "operator()(auto &&) const", + "full_name": "clanguml::t20046::clanguml::t20046::tmain()::(lambda t20046.cc:19:9)::(lambda t20046.cc:19:34)::operator()(auto &&) const", "id": "1093593470536515636", "name": "operator()", "namespace": "", @@ -169,6 +179,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20046.cc:19:9)::(lambda t20046.cc:19:34)", + "full_name": "clanguml::t20046::clanguml::t20046::tmain()::(lambda t20046.cc:19:9)::(lambda t20046.cc:19:34)", "id": "2177951153338850159", "name": "clanguml::t20046::tmain()::(lambda t20046.cc:19:9)::(lambda t20046.cc:19:34)", "namespace": "clanguml::t20046", @@ -182,6 +193,7 @@ int tmain() }, { "display_name": "a3(int)", + "full_name": "clanguml::t20046::a3(int)", "id": "1043774975066033521", "name": "a3", "namespace": "clanguml::t20046", diff --git a/docs/test_cases/t20046_sequence.svg b/docs/test_cases/t20046_sequence.svg index 1ac1a799..a78b8b44 100644 --- a/docs/test_cases/t20046_sequence.svg +++ b/docs/test_cases/t20046_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,14 +9,14 @@ - - - - - - - - + + + + + + + + @@ -25,73 +25,73 @@ - - + + tmain() - + tmain() - - + + tmain()::(lambda t20046.cc:13:15) - + tmain()::(lambda t20046.cc:13:15) - - + + tmain()::(lambda t20046.cc:13:15)::(lambda t20046.cc:14:16) - + tmain()::(lambda t20046.cc:13:15)::(lambda t20046.cc:14:16) - - + + a2(int) - + a2(int) - - + + a1<(lambda at t20046.cc:19:9)>((lambda at t20046.cc:19:9) &&) - + a1<(lambda at t20046.cc:19:9)>((lambda at t20046.cc:19:9) &&) - - + + tmain()::(lambda t20046.cc:19:9) - + tmain()::(lambda t20046.cc:19:9) - - + + tmain()::(lambda t20046.cc:19:9)::(lambda t20046.cc:19:34) - + tmain()::(lambda t20046.cc:19:9)::(lambda t20046.cc:19:34) - - + + a3(int) - + a3(int) - - - - - - - - - + + + + + + + + + operator()(auto &&) const - + operator()(auto &&) const - + @@ -101,21 +101,21 @@ - + - + operator()(auto &&) const - + operator()(auto &&) const - + diff --git a/docs/test_cases/t20047.md b/docs/test_cases/t20047.md index a6e17c7b..6c620c45 100644 --- a/docs/test_cases/t20047.md +++ b/docs/test_cases/t20047.md @@ -73,6 +73,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20047::tmain()", "id": "395335809944376006", "name": "tmain", "namespace": "clanguml::t20047", @@ -86,6 +87,7 @@ int tmain() }, { "display_name": "a1(int)", + "full_name": "clanguml::t20047::a1(int)", "id": "1143426315383292679", "name": "a1", "namespace": "clanguml::t20047", @@ -99,6 +101,7 @@ int tmain() }, { "display_name": "a2(int)", + "full_name": "clanguml::t20047::a2(int)", "id": "642420844675776100", "name": "a2", "namespace": "clanguml::t20047", @@ -112,6 +115,7 @@ int tmain() }, { "display_name": "a3(int)", + "full_name": "clanguml::t20047::a3(int)", "id": "270462331062298387", "name": "a3", "namespace": "clanguml::t20047", @@ -125,6 +129,7 @@ int tmain() }, { "display_name": "a4(int)", + "full_name": "clanguml::t20047::a4(int)", "id": "128784832900379603", "name": "a4", "namespace": "clanguml::t20047", @@ -138,6 +143,7 @@ int tmain() }, { "display_name": "a5(int)", + "full_name": "clanguml::t20047::a5(int)", "id": "2182660880755444870", "name": "a5", "namespace": "clanguml::t20047", @@ -151,6 +157,7 @@ int tmain() }, { "display_name": "a6(int)", + "full_name": "clanguml::t20047::a6(int)", "id": "1272350614275781124", "name": "a6", "namespace": "clanguml::t20047", diff --git a/docs/test_cases/t20047_sequence.svg b/docs/test_cases/t20047_sequence.svg index ebcc8115..aa2e44f4 100644 --- a/docs/test_cases/t20047_sequence.svg +++ b/docs/test_cases/t20047_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,13 +9,13 @@ - - - - - - - + + + + + + + @@ -23,86 +23,86 @@ - - + + tmain() - + tmain() - - + + a1(int) - + a1(int) - - + + a2(int) - + a2(int) - - + + a3(int) - + a3(int) - - + + a4(int) - + a4(int) - - + + a5(int) - + a5(int) - - + + a6(int) - + a6(int) - - - - - - - - + + + + + + + + - + - + - + - + - + diff --git a/docs/test_cases/t20048.md b/docs/test_cases/t20048.md index abb86ddb..69e475ab 100644 --- a/docs/test_cases/t20048.md +++ b/docs/test_cases/t20048.md @@ -72,6 +72,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20048::tmain()", "id": "1438172520221545830", "name": "tmain", "namespace": "clanguml::t20048", @@ -85,6 +86,7 @@ int tmain() }, { "display_name": "a3(int)", + "full_name": "clanguml::t20048::a3(int)", "id": "1592723040639512239", "name": "a3", "namespace": "clanguml::t20048", @@ -98,6 +100,7 @@ int tmain() }, { "display_name": "a2(int)", + "full_name": "clanguml::t20048::a2(int)", "id": "1494883525267049301", "name": "a2", "namespace": "clanguml::t20048", @@ -111,6 +114,7 @@ int tmain() }, { "display_name": "a1(int)", + "full_name": "clanguml::t20048::a1(int)", "id": "1139681416936587734", "name": "a1", "namespace": "clanguml::t20048", @@ -126,6 +130,7 @@ int tmain() "activities": [ { "display_name": "operator()(auto &&) const", + "full_name": "clanguml::t20048::tmain()::(lambda t20048.cc:26:11)::operator()(auto &&) const", "id": "1272214062049882942", "name": "operator()", "namespace": "", @@ -133,6 +138,7 @@ int tmain() } ], "display_name": "tmain()::(lambda t20048.cc:26:11)", + "full_name": "clanguml::t20048::tmain()::(lambda t20048.cc:26:11)", "id": "794500632550538124", "name": "tmain()::(lambda t20048.cc:26:11)", "namespace": "clanguml::t20048", @@ -146,6 +152,7 @@ int tmain() }, { "display_name": "a4(int)", + "full_name": "clanguml::t20048::a4(int)", "id": "986710377344543262", "name": "a4", "namespace": "clanguml::t20048", @@ -159,6 +166,7 @@ int tmain() }, { "display_name": "a6(int)", + "full_name": "clanguml::t20048::a6(int)", "id": "372194568810958399", "name": "a6", "namespace": "clanguml::t20048", @@ -172,6 +180,7 @@ int tmain() }, { "display_name": "a5(int)", + "full_name": "clanguml::t20048::a5(int)", "id": "473170110460301705", "name": "a5", "namespace": "clanguml::t20048", @@ -185,6 +194,7 @@ int tmain() }, { "display_name": "a7(int)", + "full_name": "clanguml::t20048::a7(int)", "id": "156504678810211848", "name": "a7", "namespace": "clanguml::t20048", diff --git a/docs/test_cases/t20048_sequence.svg b/docs/test_cases/t20048_sequence.svg index 904b22ab..2aa247f5 100644 --- a/docs/test_cases/t20048_sequence.svg +++ b/docs/test_cases/t20048_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,15 +9,15 @@ - - - - - - - - - + + + + + + + + + @@ -27,101 +27,101 @@ - - + + tmain() - + tmain() - - + + a3(int) - + a3(int) - - + + a2(int) - + a2(int) - - + + a1(int) - + a1(int) - - + + tmain()::(lambda t20048.cc:26:11) - + tmain()::(lambda t20048.cc:26:11) - - + + a4(int) - + a4(int) - - + + a6(int) - + a6(int) - - + + a5(int) - + a5(int) - - + + a7(int) - + a7(int) - - - - - - - - - - + + + + + + + + + + - + - + a1() adds `1` to the result of a2() - + - + This lambda calls a4() which adds `4` to it's argument - + operator()(auto &&) const - + @@ -129,29 +129,29 @@ - + a6() adds `1` to its argument - + - + a5() adds `1` to the result of a6() - + - + a7() is called via add std::async - + diff --git a/docs/test_cases/t20049.md b/docs/test_cases/t20049.md index 0064a468..ec5e04eb 100644 --- a/docs/test_cases/t20049.md +++ b/docs/test_cases/t20049.md @@ -80,6 +80,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20049::tmain()", "id": "1498198764898287853", "name": "tmain", "namespace": "clanguml::t20049", @@ -93,6 +94,7 @@ int tmain() }, { "display_name": "vector_square_add(float *,float *,float *,int)", + "full_name": "clanguml::t20049::vector_square_add(float *,float *,float *,int)", "id": "1998596618150288680", "is_cuda_kernel": true, "name": "vector_square_add", @@ -107,6 +109,7 @@ int tmain() }, { "display_name": "square(float)", + "full_name": "clanguml::t20049::square(float)", "id": "817124001270348685", "is_cuda_device": true, "name": "square", @@ -121,6 +124,7 @@ int tmain() }, { "display_name": "add(float,float)", + "full_name": "clanguml::t20049::add(float,float)", "id": "1897367040611447556", "is_cuda_device": true, "name": "add", diff --git a/docs/test_cases/t20049_sequence.svg b/docs/test_cases/t20049_sequence.svg index 12acc402..4eb6d9ff 100644 --- a/docs/test_cases/t20049_sequence.svg +++ b/docs/test_cases/t20049_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,71 +9,71 @@ - - - - - - + + + + + + - - + + tmain() - + tmain() - - + + «CUDA Kernel» vector_square_add(float *,float *,float *,int) - + «CUDA Kernel» vector_square_add(float *,float *,float *,int) - - + + «CUDA Device» square(float) - + «CUDA Device» square(float) - - + + «CUDA Device» add<float>(float,float) - + «CUDA Device» add<float>(float,float) - - - - - - + + + + + + loop - + - + - + diff --git a/docs/test_cases/t20050.md b/docs/test_cases/t20050.md index e53b500f..3cc25418 100644 --- a/docs/test_cases/t20050.md +++ b/docs/test_cases/t20050.md @@ -82,6 +82,7 @@ int tmain() "activities": [ { "display_name": "tmain()", + "full_name": "clanguml::t20050::tmain()", "id": "1047834785038011964", "name": "tmain", "namespace": "clanguml::t20050", @@ -95,6 +96,7 @@ int tmain() }, { "display_name": "vector_square_add(float *,float *,float *,int)", + "full_name": "clanguml::t20050::vector_square_add(float *,float *,float *,int)", "id": "100545266160871109", "is_cuda_kernel": true, "name": "vector_square_add", @@ -109,6 +111,7 @@ int tmain() }, { "display_name": "square(float)", + "full_name": "clanguml::t20050::square(float)", "id": "193263048716247783", "is_cuda_device": true, "name": "square", @@ -123,6 +126,7 @@ int tmain() }, { "display_name": "add(float,float)", + "full_name": "clanguml::t20050::add(float,float)", "id": "60344909513106774", "is_cuda_device": true, "name": "add", @@ -137,6 +141,7 @@ int tmain() } ], "display_name": "t20050.cu", + "full_name": "clanguml::t20050::tmain()", "id": "551473340136355806", "name": "t20050.cu", "namespace": "clanguml::t20050", diff --git a/docs/test_cases/t20050_sequence.svg b/docs/test_cases/t20050_sequence.svg index a96cf116..1acd0dc1 100644 --- a/docs/test_cases/t20050_sequence.svg +++ b/docs/test_cases/t20050_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,26 +9,26 @@ - - - - - - + + + + + + - + t20050.cu - + t20050.cu - - - - - + + + + + tmain() - + @@ -39,7 +39,7 @@ loop - + @@ -51,7 +51,7 @@ - + @@ -63,7 +63,7 @@ - + diff --git a/docs/test_cases/t20051.md b/docs/test_cases/t20051.md index fab32475..ec7a5fef 100644 --- a/docs/test_cases/t20051.md +++ b/docs/test_cases/t20051.md @@ -82,6 +82,7 @@ __global__ void vector_square_add(float *out, float *a, float *b, int n); "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20051::tmain()", "id": "33004218577871304", "name": "tmain", "namespace": "clanguml::t20051", @@ -95,6 +96,7 @@ __global__ void vector_square_add(float *out, float *a, float *b, int n); }, { "display_name": "vector_square_add(float *,float *,float *,int)", + "full_name": "clanguml::t20051::vector_square_add(float *,float *,float *,int)", "id": "1972238512532321229", "is_cuda_kernel": true, "name": "vector_square_add", diff --git a/docs/test_cases/t20051_sequence.svg b/docs/test_cases/t20051_sequence.svg index 9b8b3eaf..3322275f 100644 --- a/docs/test_cases/t20051_sequence.svg +++ b/docs/test_cases/t20051_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,27 +9,27 @@ - - + + - - + + tmain() - + tmain() - - + + «CUDA Kernel» vector_square_add(float *,float *,float *,int) - + «CUDA Kernel» vector_square_add(float *,float *,float *,int) - - - + + + diff --git a/docs/test_cases/t20052.md b/docs/test_cases/t20052.md index e2f2bd5b..6653a309 100644 --- a/docs/test_cases/t20052.md +++ b/docs/test_cases/t20052.md @@ -135,6 +135,7 @@ void tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20052::tmain()", "id": "1863374927109937538", "name": "tmain", "namespace": "clanguml::t20052", @@ -150,6 +151,7 @@ void tmain() "activities": [ { "display_name": "a()", + "full_name": "clanguml::t20052::A::a()", "id": "1226536010860143477", "name": "a", "namespace": "", @@ -163,6 +165,7 @@ void tmain() }, { "display_name": "aa()", + "full_name": "clanguml::t20052::A::aa()", "id": "152397826074008213", "name": "aa", "namespace": "", @@ -176,6 +179,7 @@ void tmain() }, { "display_name": "aaa()", + "full_name": "clanguml::t20052::A::aaa()", "id": "1337804153305761200", "name": "aaa", "namespace": "", @@ -189,6 +193,7 @@ void tmain() } ], "display_name": "A", + "full_name": "clanguml::t20052::A", "id": "1703104288786661165", "name": "A", "namespace": "clanguml::t20052", @@ -204,6 +209,7 @@ void tmain() "activities": [ { "display_name": "b()", + "full_name": "clanguml::t20052::B::b()", "id": "319515743780574134", "name": "b", "namespace": "", @@ -217,6 +223,7 @@ void tmain() }, { "display_name": "bb()", + "full_name": "clanguml::t20052::B::bb()", "id": "647068274411777494", "name": "bb", "namespace": "", @@ -230,6 +237,7 @@ void tmain() }, { "display_name": "bbb()", + "full_name": "clanguml::t20052::B::bbb()", "id": "849373810301162421", "name": "bbb", "namespace": "", @@ -243,6 +251,7 @@ void tmain() } ], "display_name": "B", + "full_name": "clanguml::t20052::B", "id": "1858368487431426893", "name": "B", "namespace": "clanguml::t20052", @@ -258,6 +267,7 @@ void tmain() "activities": [ { "display_name": "c()", + "full_name": "clanguml::t20052::C::c()", "id": "286735272236693235", "name": "c", "namespace": "", @@ -271,6 +281,7 @@ void tmain() }, { "display_name": "cc()", + "full_name": "clanguml::t20052::C::cc()", "id": "927328030188215717", "name": "cc", "namespace": "", @@ -284,6 +295,7 @@ void tmain() }, { "display_name": "ccc()", + "full_name": "clanguml::t20052::C::ccc()", "id": "733299138189220355", "name": "ccc", "namespace": "", @@ -297,6 +309,7 @@ void tmain() } ], "display_name": "C", + "full_name": "clanguml::t20052::C", "id": "695917114097253548", "name": "C", "namespace": "clanguml::t20052", @@ -312,6 +325,7 @@ void tmain() "activities": [ { "display_name": "R((lambda at t20052.cc:86:9) &&)", + "full_name": "clanguml::t20052::R<(lambda at t20052.cc:86:9)>::R((lambda at t20052.cc:86:9) &&)", "id": "1771911385519841377", "name": "R", "namespace": "", @@ -325,6 +339,7 @@ void tmain() }, { "display_name": "r()", + "full_name": "clanguml::t20052::R<(lambda at t20052.cc:86:9)>::r()", "id": "1643468997390681958", "name": "r", "namespace": "", @@ -338,6 +353,7 @@ void tmain() } ], "display_name": "R<(lambda at t20052.cc:86:9)>", + "full_name": "clanguml::t20052::R<(lambda at t20052.cc:86:9)>", "id": "548336024237507357", "name": "R", "namespace": "clanguml::t20052", @@ -353,6 +369,7 @@ void tmain() "activities": [ { "display_name": "add5(int) const", + "full_name": "clanguml::t20052::D::add5(int) const", "id": "2099569549236534730", "name": "add5", "namespace": "", @@ -366,6 +383,7 @@ void tmain() } ], "display_name": "D", + "full_name": "clanguml::t20052::D", "id": "1091266475405978871", "name": "D", "namespace": "clanguml::t20052", @@ -581,6 +599,46 @@ void tmain() }, "type": "message" }, + { + "from": { + "activity_id": "1226536010860143477", + "participant_id": "1703104288786661165" + }, + "name": "aa()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 16, + "file": "t20052.cc", + "line": 11, + "translation_unit": "t20052.cc" + }, + "to": { + "activity_id": "152397826074008213", + "participant_id": "1703104288786661165" + }, + "type": "message" + }, + { + "from": { + "activity_id": "152397826074008213", + "participant_id": "1703104288786661165" + }, + "name": "aaa()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 17, + "file": "t20052.cc", + "line": 13, + "translation_unit": "t20052.cc" + }, + "to": { + "activity_id": "1337804153305761200", + "participant_id": "1703104288786661165" + }, + "type": "message" + }, { "from": { "activity_id": "1863374927109937538", @@ -601,6 +659,46 @@ void tmain() }, "type": "message" }, + { + "from": { + "activity_id": "319515743780574134", + "participant_id": "1858368487431426893" + }, + "name": "bb()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 16, + "file": "t20052.cc", + "line": 19, + "translation_unit": "t20052.cc" + }, + "to": { + "activity_id": "647068274411777494", + "participant_id": "1858368487431426893" + }, + "type": "message" + }, + { + "from": { + "activity_id": "647068274411777494", + "participant_id": "1858368487431426893" + }, + "name": "bbb()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 17, + "file": "t20052.cc", + "line": 21, + "translation_unit": "t20052.cc" + }, + "to": { + "activity_id": "849373810301162421", + "participant_id": "1858368487431426893" + }, + "type": "message" + }, { "from": { "activity_id": "1863374927109937538", @@ -661,6 +759,46 @@ void tmain() }, "type": "message" }, + { + "from": { + "activity_id": "286735272236693235", + "participant_id": "695917114097253548" + }, + "name": "cc()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 16, + "file": "t20052.cc", + "line": 29, + "translation_unit": "t20052.cc" + }, + "to": { + "activity_id": "927328030188215717", + "participant_id": "695917114097253548" + }, + "type": "message" + }, + { + "from": { + "activity_id": "927328030188215717", + "participant_id": "695917114097253548" + }, + "name": "ccc()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 17, + "file": "t20052.cc", + "line": 31, + "translation_unit": "t20052.cc" + }, + "to": { + "activity_id": "733299138189220355", + "participant_id": "695917114097253548" + }, + "type": "message" + }, { "from": { "activity_id": "1863374927109937538", diff --git a/docs/test_cases/t20052_sequence.svg b/docs/test_cases/t20052_sequence.svg index f571b552..15dfb7cc 100644 --- a/docs/test_cases/t20052_sequence.svg +++ b/docs/test_cases/t20052_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,217 +9,217 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - + + tmain() - + tmain() - - + + A - + A - - + + B - + B - - + + C - + C - - + + R<(lambda at t20052.cc:86:9)> - + R<(lambda at t20052.cc:86:9)> - - + + D - + D - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + a() - + aa() - + aaa() - + b() - + bb() - + bbb() - + c() - + cc() - + ccc() - + a() - + aa() - + aaa() - + b() - + bb() - + bbb() - + R((lambda at t20052.cc:86:9) &&) - + r() - + c() - + cc() - + ccc() - + add5(int) const diff --git a/docs/test_cases/t20053.md b/docs/test_cases/t20053.md index 82b4d6a4..017d3d29 100644 --- a/docs/test_cases/t20053.md +++ b/docs/test_cases/t20053.md @@ -58,6 +58,7 @@ int tmain() "participants": [ { "display_name": "tmain()", + "full_name": "clanguml::t20053::tmain()", "id": "1989009774042525491", "name": "tmain", "namespace": "clanguml::t20053", @@ -71,6 +72,7 @@ int tmain() }, { "display_name": "a2(int)", + "full_name": "clanguml::t20053::a2(int)", "id": "670119640253232066", "name": "a2", "namespace": "clanguml::t20053", @@ -83,7 +85,8 @@ int tmain() "type": "function" }, { - "display_name": "a1<(lambda at t20053.cc:23:9)>((lambda at /home/bartek/devel/clang-uml/tests/t20053/t20053.cc:23:9) &&)", + "display_name": "a1<(lambda at t20053.cc:23:9)>((lambda at t20053.cc:23:9) &&)", + "full_name": "clanguml::t20053::a1<(lambda at t20053.cc:23:9)>((lambda at /home/bartek/devel/clang-uml/tests/t20053/t20053.cc:23:9) &&)", "id": "967684327663938310", "name": "a1", "namespace": "clanguml::t20053", @@ -97,6 +100,7 @@ int tmain() }, { "display_name": "a3(int)", + "full_name": "clanguml::t20053::a3(int)", "id": "1586707721117132930", "name": "a3", "namespace": "clanguml::t20053", diff --git a/docs/test_cases/t20053_sequence.svg b/docs/test_cases/t20053_sequence.svg index 436f632d..06a5807a 100644 --- a/docs/test_cases/t20053_sequence.svg +++ b/docs/test_cases/t20053_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,53 +9,53 @@ - - - - + + + + - - + + tmain() - + tmain() - - + + a2(int) - + a2(int) - - + + a1<(lambda at t20053.cc:23:9)>((lambda at t20053.cc:23:9) &&) - + a1<(lambda at t20053.cc:23:9)>((lambda at t20053.cc:23:9) &&) - - + + a3(int) - + a3(int) - - - - - + + + + + - + - + diff --git a/docs/test_cases/t30001_package.svg b/docs/test_cases/t30001_package.svg index 77ad7870..d3a4d0c4 100644 --- a/docs/test_cases/t30001_package.svg +++ b/docs/test_cases/t30001_package.svg @@ -1,6 +1,6 @@ - + @@ -10,63 +10,63 @@ Basic package diagram example - - + + A - - + + AA - - + + B - - + + AA - - + + AAA - - + + BBB - - + + BB - - + + AAA - - + + BBB - - + + BB - + A AAA note... - + This is namespace AA in namespace A - + This is namespace AA in namespace B diff --git a/docs/test_cases/t30002_package.svg b/docs/test_cases/t30002_package.svg index a1f50d06..895dfde2 100644 --- a/docs/test_cases/t30002_package.svg +++ b/docs/test_cases/t30002_package.svg @@ -1,6 +1,6 @@ - + @@ -9,118 +9,118 @@ - - + + A - - + + AA - - + + B - - + + BB - - + + A1 - - + + A2 - - + + A3 - - + + A4 - - + + A5 - - + + A6 - - + + A7 - - + + A8 - - + + A9 - - + + A10 - - + + A11 - - + + A12 - - + + A13 - - + + A14 - - + + A15 - - + + A16 - - + + A17 - - + + A18 - - + + BBB diff --git a/docs/test_cases/t30003_package.svg b/docs/test_cases/t30003_package.svg index 5350f351..3e6e3c13 100644 --- a/docs/test_cases/t30003_package.svg +++ b/docs/test_cases/t30003_package.svg @@ -1,6 +1,6 @@ - + @@ -9,35 +9,35 @@ - - + + ns1 - - + + ns3 «deprecated» - - + + ns1 - - + + ns2_v1_0_0 - - + + ns2_v0_9_0 «deprecated» - - + + ns2 diff --git a/docs/test_cases/t30003_package_mermaid.svg b/docs/test_cases/t30003_package_mermaid.svg index 0a3b23e0..de53726e 100644 --- a/docs/test_cases/t30003_package_mermaid.svg +++ b/docs/test_cases/t30003_package_mermaid.svg @@ -1,4 +1,4 @@ - + @@ -20,81 +20,84 @@ - - - + + + + + +
+ ns3 +
+
+
+
+ + + + +
+ ns1 +
+
+
+
+ + + + +
+ ns1 +
+
+
+
+
+ + + + + + + +
+ +
+
+
+
+
- - - - - - -
- ns1 -
-
-
-
- - - - -
- ns3 -
-
-
-
+ + + + + +
+ ns2 +
+
- - + + + + + + +
+ ns2_v1_0_0 +
+
- - - - -
- -
-
-
-
-
- - - - - - -
- ns2_v1_0_0 -
-
-
-
- - - - - -
- ns2 -
-
-
-
- - - - - -
- ns2_v0_9_0 -
-
-
-
+
+ + + + + +
+ ns2_v0_9_0 +
+
diff --git a/docs/test_cases/t30004_package.svg b/docs/test_cases/t30004_package.svg index d78766a5..e7b9b8c1 100644 --- a/docs/test_cases/t30004_package.svg +++ b/docs/test_cases/t30004_package.svg @@ -1,6 +1,6 @@ - + @@ -9,40 +9,40 @@ - - + + A - + Package AAA. - + Package BBB. - + CCCC package note. - + We skipped DDD. - - + + AAA - - + + BBB - - + + CCC - - + + EEE diff --git a/docs/test_cases/t30005_package.svg b/docs/test_cases/t30005_package.svg index 4703a42e..0e9f0237 100644 --- a/docs/test_cases/t30005_package.svg +++ b/docs/test_cases/t30005_package.svg @@ -1,6 +1,6 @@ - + @@ -9,48 +9,48 @@ - - + + A - - + + AA - - + + B - - + + BB - - + + C - - + + CC - - + + AAA - - + + BBB - - + + CCC diff --git a/docs/test_cases/t30006_package.svg b/docs/test_cases/t30006_package.svg index 196a48e7..d1e557bc 100644 --- a/docs/test_cases/t30006_package.svg +++ b/docs/test_cases/t30006_package.svg @@ -1,6 +1,6 @@ - + @@ -9,22 +9,22 @@ - - + + B - - + + A - - + + C - + Top A note. diff --git a/docs/test_cases/t30007_package.svg b/docs/test_cases/t30007_package.svg index 6137613d..afce72b5 100644 --- a/docs/test_cases/t30007_package.svg +++ b/docs/test_cases/t30007_package.svg @@ -1,6 +1,6 @@ - + @@ -9,27 +9,27 @@ - - + + A - - + + B - - + + AA - - + + C - + Compare layout with t30006. diff --git a/docs/test_cases/t30008_package.svg b/docs/test_cases/t30008_package.svg index 008fd71f..19def6ca 100644 --- a/docs/test_cases/t30008_package.svg +++ b/docs/test_cases/t30008_package.svg @@ -1,6 +1,6 @@ - + @@ -9,43 +9,43 @@ - - + + dependants - - + + dependencies - - + + A - - + + B - - + + C - - + + D - - + + E - - + + F diff --git a/docs/test_cases/t30009_package.svg b/docs/test_cases/t30009_package.svg index 73bb507c..8a4ad588 100644 --- a/docs/test_cases/t30009_package.svg +++ b/docs/test_cases/t30009_package.svg @@ -1,6 +1,6 @@ - + @@ -9,53 +9,53 @@ - - + + One - - + + Two - - + + B - - + + D - - + + A - - + + C - - + + A - - + + B - - + + C - - + + D diff --git a/docs/test_cases/t30010_package.svg b/docs/test_cases/t30010_package.svg index 4d195056..dc4326a8 100644 --- a/docs/test_cases/t30010_package.svg +++ b/docs/test_cases/t30010_package.svg @@ -1,6 +1,6 @@ - + @@ -9,31 +9,31 @@ - + libraries - - + + lib1 - - + + lib2 - - + + lib3 - - + + lib4 - - + + app diff --git a/docs/test_cases/t30011_package.svg b/docs/test_cases/t30011_package.svg index 083bc07d..48decaf7 100644 --- a/docs/test_cases/t30011_package.svg +++ b/docs/test_cases/t30011_package.svg @@ -1,6 +1,6 @@ - + @@ -9,31 +9,31 @@ - + libraries - - + + lib1 - - + + lib2 - - + + lib3 - - + + lib4 - - + + app diff --git a/docs/test_cases/t30012_package.svg b/docs/test_cases/t30012_package.svg index 3bde79d3..758fbcf5 100644 --- a/docs/test_cases/t30012_package.svg +++ b/docs/test_cases/t30012_package.svg @@ -1,6 +1,6 @@ - + @@ -9,26 +9,26 @@ - + app - - + + lib1 - - + + mod1 - - + + mod2 - - + + lib2 diff --git a/docs/test_cases/t30013_package.svg b/docs/test_cases/t30013_package.svg index 0a929f83..3d3f3e54 100644 --- a/docs/test_cases/t30013_package.svg +++ b/docs/test_cases/t30013_package.svg @@ -1,6 +1,6 @@ - + @@ -9,98 +9,98 @@ - - + + mod1 - - + + mod2 - - + + mod3 - - + + mod4 - - + + mod5 - - + + mod6 - - + + mod7 - - + + mod8 - - + + mod9 - - + + mod10 - - + + mod11 - - + + mod12 - - + + mod13 - - + + mod14 - - + + mod15 - - + + mod16 - - + + mod17 - - + + mod18 - - + + app diff --git a/docs/test_cases/t30014_package.svg b/docs/test_cases/t30014_package.svg index 7187b30b..54fd26bb 100644 --- a/docs/test_cases/t30014_package.svg +++ b/docs/test_cases/t30014_package.svg @@ -1,6 +1,6 @@ - + @@ -9,21 +9,21 @@ - + app - - + + :lib1 - - + + mod1 - - + + :lib2 diff --git a/docs/test_cases/t30015_package.svg b/docs/test_cases/t30015_package.svg index af59c171..fecb8b28 100644 --- a/docs/test_cases/t30015_package.svg +++ b/docs/test_cases/t30015_package.svg @@ -1,6 +1,6 @@ - + @@ -9,101 +9,101 @@ - + lib1 - - + + :mod1 - - + + :mod2 - - + + :mod3 - - + + :mod4 - - + + :mod5 - - + + :mod6 - - + + :mod7 - - + + :mod8 - - + + :mod9 - - + + :mod10 - - + + :mod11 - - + + :mod12 - - + + :mod13 - - + + :mod14 - - + + :mod15 - - + + :mod16 - - + + :mod17 - - + + :mod18 - - + + app diff --git a/docs/test_cases/t40001_include.svg b/docs/test_cases/t40001_include.svg index d2d85209..f0097a3a 100644 --- a/docs/test_cases/t40001_include.svg +++ b/docs/test_cases/t40001_include.svg @@ -1,6 +1,6 @@ - + @@ -10,41 +10,41 @@ Basic include diagram example - + src - + include - + lib1 - - + + t40001.cc - - + + t40001_include1.h - + lib1.h - + string - + vector - + yaml-cpp/yaml.h - + This is a lib1 include dir - + This is a t40001_include1.h include file diff --git a/docs/test_cases/t40001_include_mermaid.svg b/docs/test_cases/t40001_include_mermaid.svg index be8bfda8..dcdbada3 100644 --- a/docs/test_cases/t40001_include_mermaid.svg +++ b/docs/test_cases/t40001_include_mermaid.svg @@ -138,7 +138,7 @@ - + @@ -151,7 +151,7 @@ - + @@ -164,7 +164,7 @@ - + diff --git a/docs/test_cases/t40002_include.svg b/docs/test_cases/t40002_include.svg index db32864a..b0420a30 100644 --- a/docs/test_cases/t40002_include.svg +++ b/docs/test_cases/t40002_include.svg @@ -1,6 +1,6 @@ - + @@ -9,46 +9,46 @@ - + src - + lib1 - + lib2 - + include - + lib1 - + lib2 - - + + t40002.cc - - + + lib1.cc - - + + lib2.cc - - + + lib1.h - - + + lib2.h diff --git a/docs/test_cases/t40002_include_mermaid.svg b/docs/test_cases/t40002_include_mermaid.svg index 71c3ddaa..bd4c0829 100644 --- a/docs/test_cases/t40002_include_mermaid.svg +++ b/docs/test_cases/t40002_include_mermaid.svg @@ -137,7 +137,7 @@ - + @@ -150,7 +150,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -176,7 +176,7 @@ - + @@ -189,7 +189,7 @@ - + diff --git a/docs/test_cases/t40003_include.svg b/docs/test_cases/t40003_include.svg index e365250e..18c14959 100644 --- a/docs/test_cases/t40003_include.svg +++ b/docs/test_cases/t40003_include.svg @@ -1,6 +1,6 @@ - + @@ -9,62 +9,62 @@ - + src - + dependants - + dependencies - + include - + dependants - + dependencies - - + + t1.cc - - + + t2.cc - - + + t3.h - - + + t2.h - + t1.h - - + + t3.h - - + + t2.h - + t1.h - - + + t5.h diff --git a/docs/test_cases/t40003_include_mermaid.svg b/docs/test_cases/t40003_include_mermaid.svg index d0b53bb6..64880eee 100644 --- a/docs/test_cases/t40003_include_mermaid.svg +++ b/docs/test_cases/t40003_include_mermaid.svg @@ -167,7 +167,7 @@ - + @@ -180,7 +180,7 @@ - + @@ -193,7 +193,7 @@ - + @@ -206,7 +206,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -232,7 +232,7 @@ - + @@ -245,7 +245,7 @@ - + @@ -258,7 +258,7 @@ - + @@ -271,7 +271,7 @@ - + diff --git a/src/class_diagram/generators/json/class_diagram_generator.cc b/src/class_diagram/generators/json/class_diagram_generator.cc index 22aae5ac..f8cb28d5 100644 --- a/src/class_diagram/generators/json/class_diagram_generator.cc +++ b/src/class_diagram/generators/json/class_diagram_generator.cc @@ -76,6 +76,8 @@ void to_json(nlohmann::json &j, const class_method &c) j["is_move_assignment"] = c.is_move_assignment(); j["is_copy_assignment"] = c.is_copy_assignment(); j["is_operator"] = c.is_operator(); + j["template_parameters"] = c.template_params(); + j["display_name"] = c.display_name(); j["parameters"] = c.parameters(); } @@ -156,7 +158,10 @@ void generator::generate_top_level_elements(nlohmann::json &parent) const { for (const auto &p : model()) { if (auto *pkg = dynamic_cast(p.get()); pkg) { - if (!pkg->is_empty()) + if (!pkg->is_empty() && + !pkg->all_of([this](const common::model::element &e) { + return !model().should_include(e); + })) generate(*pkg, parent); } else if (auto *cls = dynamic_cast(p.get()); cls) { @@ -198,7 +203,10 @@ void generator::generate(const package &p, nlohmann::json &parent) const for (const auto &subpackage : p) { if (dynamic_cast(subpackage.get()) != nullptr) { const auto &sp = dynamic_cast(*subpackage); - if (!sp.is_empty()) { + if (!sp.is_empty() && + !sp.all_of([this](const common::model::element &e) { + return !model().should_include(e); + })) { if (config().generate_packages()) generate(sp, package_object); else @@ -239,18 +247,47 @@ void generator::generate(const package &p, nlohmann::json &parent) const void generator::generate(const class_ &c, nlohmann::json &parent) const { nlohmann::json object = c; + + // Perform config dependent postprocessing on generated class + if (!config().generate_fully_qualified_name()) + object["display_name"] = + common::generators::json::render_name(c.full_name_no_ns()); + + for (auto &tp : object["template_parameters"]) { + if (tp.contains("type") && tp.at("type").is_string()) { + tp["type"] = config().using_namespace().relative(tp.at("type")); + } + } + for (auto &tp : object["members"]) { + if (tp.contains("type") && tp.at("type").is_string()) { + tp["type"] = config().using_namespace().relative(tp.at("type")); + } + } + + std::string object_str = object.dump(2); + parent["elements"].push_back(std::move(object)); } void generator::generate(const enum_ &e, nlohmann::json &parent) const { nlohmann::json object = e; + + if (!config().generate_fully_qualified_name()) + object["display_name"] = + common::generators::json::render_name(e.full_name_no_ns()); + parent["elements"].push_back(std::move(object)); } void generator::generate(const concept_ &c, nlohmann::json &parent) const { nlohmann::json object = c; + + if (!config().generate_fully_qualified_name()) + object["display_name"] = + common::generators::json::render_name(c.full_name_no_ns()); + parent["elements"].push_back(std::move(object)); } @@ -282,6 +319,9 @@ void generator::generate_relationships( const class_ &c, nlohmann::json &parent) const { for (const auto &r : c.relationships()) { + if (!model().should_include(r)) + continue; + auto target_element = model().get(r.destination()); if (!target_element.has_value()) { LOG_DBG("Skipping {} relation from {} to {} due " @@ -310,6 +350,9 @@ void generator::generate_relationships( const enum_ &c, nlohmann::json &parent) const { for (const auto &r : c.relationships()) { + if (!model().should_include(r)) + continue; + auto target_element = model().get(r.destination()); if (!target_element.has_value()) { LOG_DBG("Skipping {} relation from {} to {} due " @@ -328,6 +371,9 @@ void generator::generate_relationships( const concept_ &c, nlohmann::json &parent) const { for (const auto &r : c.relationships()) { + if (!model().should_include(r)) + continue; + auto target_element = model().get(r.destination()); if (!target_element.has_value()) { LOG_DBG("Skipping {} relation from {} to {} due " diff --git a/src/class_diagram/generators/mermaid/class_diagram_generator.cc b/src/class_diagram/generators/mermaid/class_diagram_generator.cc index 416e0ae8..436d60b4 100644 --- a/src/class_diagram/generators/mermaid/class_diagram_generator.cc +++ b/src/class_diagram/generators/mermaid/class_diagram_generator.cc @@ -300,7 +300,8 @@ void generator::generate(const concept_ &c, std::ostream &ostr) const << fmt::format("\"({})\"\n", fmt::join(parameters, ",")); for (const auto &req : c.requires_statements()) { - ostr << indent(2) << fmt::format("\"{}\"\n", render_name(req)); + ostr << indent(2) + << fmt::format("\"{}\"\n", render_name(req, false)); } } diff --git a/src/class_diagram/generators/plantuml/class_diagram_generator.cc b/src/class_diagram/generators/plantuml/class_diagram_generator.cc index 0a5b6fa8..67016667 100644 --- a/src/class_diagram/generators/plantuml/class_diagram_generator.cc +++ b/src/class_diagram/generators/plantuml/class_diagram_generator.cc @@ -67,7 +67,7 @@ void generator::generate_alias(const class_ &c, std::ostream &ostr) const class_type = "abstract"; std::string full_name; - if (config().generate_fully_qualified_name()) + if (!config().generate_fully_qualified_name()) full_name = c.full_name_no_ns(); else full_name = c.full_name(); @@ -89,7 +89,7 @@ void generator::generate_alias(const enum_ &e, std::ostream &ostr) const { print_debug(e, ostr); - if (config().generate_fully_qualified_name()) + if (!config().generate_fully_qualified_name()) ostr << "enum" << " \"" << e.name(); else @@ -106,7 +106,7 @@ void generator::generate_alias(const concept_ &c, std::ostream &ostr) const { print_debug(c, ostr); - if (config().generate_fully_qualified_name()) + if (!config().generate_fully_qualified_name()) ostr << "class" << " \"" << c.full_name_no_ns(); else diff --git a/src/class_diagram/model/class_method.cc b/src/class_diagram/model/class_method.cc index 9d2052ea..7daf4c47 100644 --- a/src/class_diagram/model/class_method.cc +++ b/src/class_diagram/model/class_method.cc @@ -26,6 +26,26 @@ class_method::class_method(common::model::access_t access, { } +void class_method::update(const common::model::namespace_ &un) +{ + if (template_params().empty()) { + set_display_name(name()); + } + else { + std::stringstream template_params_str; + render_template_params(template_params_str, un, true); + set_display_name( + fmt::format("{}{}", name(), template_params_str.str())); + } +} + +std::string class_method::display_name() const { return display_name_; } + +void class_method::set_display_name(const std::string &display_name) +{ + display_name_ = display_name; +} + bool class_method::is_pure_virtual() const { return is_pure_virtual_; } void class_method::is_pure_virtual(bool is_pure_virtual) diff --git a/src/class_diagram/model/class_method.h b/src/class_diagram/model/class_method.h index 4cf4344b..6c556d57 100644 --- a/src/class_diagram/model/class_method.h +++ b/src/class_diagram/model/class_method.h @@ -46,6 +46,17 @@ public: ~class_method() override = default; + void update(const common::model::namespace_ &un); + + /** + * @brief Method name including template parameters/arguments if any + * + * @return String representation of the methods display name + */ + std::string display_name() const; + + void set_display_name(const std::string &display_name); + /** * @brief Whether the method is pure virtual. * @@ -282,5 +293,7 @@ private: bool is_move_assignment_{false}; bool is_copy_assignment_{false}; bool is_operator_{false}; + + std::string display_name_; }; } // namespace clanguml::class_diagram::model diff --git a/src/class_diagram/visitor/translation_unit_visitor.cc b/src/class_diagram/visitor/translation_unit_visitor.cc index fef69cd3..6b05d751 100644 --- a/src/class_diagram/visitor/translation_unit_visitor.cc +++ b/src/class_diagram/visitor/translation_unit_visitor.cc @@ -1187,7 +1187,8 @@ void translation_unit_visitor::process_method( } class_method method{common::access_specifier_to_access_t(mf.getAccess()), - util::trim(method_name), method_return_type}; + util::trim(method_name), + config().simplify_template_type(method_return_type)}; process_method_properties(mf, c, method_name, method); @@ -1266,6 +1267,8 @@ void translation_unit_visitor::process_method( process_function_parameter_find_relationships_in_autotype(c, atsp); } + method.update(config().using_namespace()); + if (diagram().should_include(method)) { LOG_DBG("Adding method: {}", method.name()); @@ -1390,6 +1393,8 @@ void translation_unit_visitor::process_template_method( process_function_parameter(*param, method, c); } + method.update(config().using_namespace()); + if (diagram().should_include(method)) { LOG_DBG("Adding method: {}", method.name()); @@ -1678,7 +1683,9 @@ void translation_unit_visitor::process_static_field( class_member field{ common::access_specifier_to_access_t(field_declaration.getAccess()), - field_declaration.getNameAsString(), type_name}; + field_declaration.getNameAsString(), + config().simplify_template_type(type_name)}; + field.is_static(true); process_comment(field_declaration, field); @@ -1769,7 +1776,7 @@ void translation_unit_visitor::process_field( class_member field{ common::access_specifier_to_access_t(field_declaration.getAccess()), - field_name, field_type_str}; + field_name, config().simplify_template_type(field_type_str)}; // Parse the field comment process_comment(field_declaration, field); diff --git a/src/common/generators/json/generator.cc b/src/common/generators/json/generator.cc index e1fa27c5..79622391 100644 --- a/src/common/generators/json/generator.cc +++ b/src/common/generators/json/generator.cc @@ -18,18 +18,10 @@ #include "generator.h" -namespace clanguml::common::model { +namespace clanguml::common { +namespace model { using nlohmann::json; -namespace detail { -std::string render_name(std::string name) -{ - util::replace_all(name, "##", "::"); - - return name; -} -} // namespace detail - void to_json(nlohmann::json &j, const source_location &sl) { j = json{{"file", sl.file_relative()}, @@ -40,9 +32,10 @@ void to_json(nlohmann::json &j, const source_location &sl) void to_json(nlohmann::json &j, const element &c) { j = json{{"id", std::to_string(c.id())}, - {"name", detail::render_name(c.name())}, + {"name", common::generators::json::render_name(c.name())}, {"namespace", c.get_namespace().to_string()}, {"type", c.type_name()}, - {"display_name", detail::render_name(c.full_name(true))}}; + {"display_name", + common::generators::json::render_name(c.full_name(true))}}; if (const auto &comment = c.comment(); comment) j["comment"] = comment.value(); @@ -81,4 +74,16 @@ void to_json(nlohmann::json &j, const relationship &c) if (const auto &comment = c.comment(); comment) j["comment"] = comment.value(); } -} // namespace clanguml::common::model +} // namespace model + +namespace generators::json { + +std::string render_name(std::string name) +{ + util::replace_all(name, "##", "::"); + + return name; +} + +} // namespace generators::json +} // namespace clanguml::common diff --git a/src/common/generators/json/generator.h b/src/common/generators/json/generator.h index dea6b3d4..3554b8f5 100644 --- a/src/common/generators/json/generator.h +++ b/src/common/generators/json/generator.h @@ -51,6 +51,8 @@ using clanguml::common::model::element; using clanguml::common::model::message_t; using clanguml::common::model::relationship_t; +std::string render_name(std::string name); + /** * @brief Base class for diagram generators * diff --git a/src/common/generators/mermaid/generator.cc b/src/common/generators/mermaid/generator.cc index ba882f46..9ceb6877 100644 --- a/src/common/generators/mermaid/generator.cc +++ b/src/common/generators/mermaid/generator.cc @@ -78,12 +78,14 @@ std::string indent(const unsigned level) return std::string(level * kIndentWidth, ' '); // NOLINT } -std::string render_name(std::string name) +std::string render_name(std::string name, bool round_brackets) { util::replace_all(name, "<", "<"); util::replace_all(name, ">", ">"); - util::replace_all(name, "(", "("); - util::replace_all(name, ")", ")"); + if (round_brackets) { + util::replace_all(name, "(", "("); + util::replace_all(name, ")", ")"); + } util::replace_all(name, "##", "::"); util::replace_all(name, "{", "{"); util::replace_all(name, "}", "}"); diff --git a/src/common/generators/mermaid/generator.h b/src/common/generators/mermaid/generator.h index 9333d8b4..2fc67662 100644 --- a/src/common/generators/mermaid/generator.h +++ b/src/common/generators/mermaid/generator.h @@ -44,7 +44,7 @@ std::string to_mermaid(message_t r); std::string indent(unsigned level); -std::string render_name(std::string name); +std::string render_name(std::string name, bool round_brackets = true); /** * @brief Base class for diagram generators diff --git a/src/common/model/diagram.cc b/src/common/model/diagram.cc index b551792d..39168e27 100644 --- a/src/common/model/diagram.cc +++ b/src/common/model/diagram.cc @@ -78,6 +78,11 @@ bool diagram::should_include(const namespace_ &ns) const return filter_->should_include(ns); } +bool diagram::should_include(relationship r) const +{ + return should_include(r.type()); +} + bool diagram::should_include(const relationship_t r) const { if (filter_.get() == nullptr) diff --git a/src/config/config.cc b/src/config/config.cc index 603cfb8b..03b472ab 100644 --- a/src/config/config.cc +++ b/src/config/config.cc @@ -268,8 +268,8 @@ std::string inheritable_diagram_options::simplify_template_type( bool inheritable_diagram_options::generate_fully_qualified_name() const { - return generate_packages() && - (package_type() == package_type_t::kNamespace); + return (package_type() == package_type_t::kNamespace) && + !generate_packages(); } std::vector diagram::get_translation_units() const diff --git a/src/package_diagram/generators/mermaid/package_diagram_generator.cc b/src/package_diagram/generators/mermaid/package_diagram_generator.cc index 1962d8c6..e2beff79 100644 --- a/src/package_diagram/generators/mermaid/package_diagram_generator.cc +++ b/src/package_diagram/generators/mermaid/package_diagram_generator.cc @@ -89,7 +89,7 @@ void generator::generate(const package &p, std::ostream &ostr) const << "]\n"; if (p.is_deprecated()) - ostr << indent(1) << "%% <>"; + ostr << indent(1) << "%% <>\n"; } for (const auto &subpackage : p) { diff --git a/src/sequence_diagram/generators/json/sequence_diagram_generator.cc b/src/sequence_diagram/generators/json/sequence_diagram_generator.cc index 3c0bdfec..ad2b206d 100644 --- a/src/sequence_diagram/generators/json/sequence_diagram_generator.cc +++ b/src/sequence_diagram/generators/json/sequence_diagram_generator.cc @@ -40,6 +40,8 @@ void to_json(nlohmann::json &j, const participant &c) j["name"] = dynamic_cast(c).method_name(); } + j["full_name"] = generators::json::render_name(c.full_name(false)); + if (c.type_name() == "function" || c.type_name() == "function_template") { const auto &f = dynamic_cast(c); if (f.is_cuda_kernel()) @@ -172,7 +174,7 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const dynamic_cast(m); msg["scope"] = to_string(m.message_scope()); - msg["return_type"] = m.return_type(); + msg["return_type"] = config().simplify_template_type(m.return_type()); parent["messages"].push_back(std::move(msg)); @@ -263,8 +265,10 @@ void generator::process_call_message( visited.push_back(m.from()); if (m.in_static_declaration_context()) { - if (util::contains(already_generated_in_static_context_, m)) + if (util::contains(already_generated_in_static_context_, m)) { + visited.pop_back(); return; + } already_generated_in_static_context_.push_back(m); } @@ -286,6 +290,8 @@ void generator::process_call_message( else LOG_DBG("Skipping activity {} --> {} - missing sequence {}", m.from(), m.to(), m.to()); + + visited.pop_back(); } void generator::process_while_message(const message &m) const @@ -566,6 +572,12 @@ common::id_t generator::generate_participant( .value() .class_id(); + LOG_DBG("Generating JSON method participant: {}", + model() + .get_participant(participant_id) + .value() + .full_name(false)); + if (!is_participant_generated(class_participant_id)) { const auto &class_participant = model() @@ -578,6 +590,13 @@ common::id_t generator::generate_participant( json_["participants"].push_back(class_participant); json_["participants"].back()["activities"].push_back(participant); + // Perform config dependent postprocessing on generated class + const auto class_participant_full_name = + class_participant.full_name(false); + + json_["participants"].back().at("display_name") = + make_display_name(class_participant_full_name); + return class_participant_id; } @@ -805,7 +824,8 @@ void generator::generate_diagram(nlohmann::json &parent) const if (from.value().type_name() == "method" || config().combine_free_functions_into_file_participants()) { - sequence["return_type"] = from.value().return_type(); + sequence["return_type"] = + make_display_name(from.value().return_type()); } parent["sequences"].push_back(std::move(sequence)); @@ -816,6 +836,24 @@ void generator::generate_diagram(nlohmann::json &parent) const } } + // Perform config dependent postprocessing on generated participants + for (auto &p : json_["participants"]) { + if (p.contains("display_name")) { + p["display_name"] = make_display_name(p["display_name"]); + } + } + parent["participants"] = json_["participants"]; } + +std::string generator::make_display_name(const std::string &full_name) const +{ + auto result = config().simplify_template_type(full_name); + result = config().using_namespace().relative(result); + common::ensure_lambda_type_is_relative(config(), result); + result = render_name(result); + + return result; +} + } // namespace clanguml::sequence_diagram::generators::json diff --git a/src/sequence_diagram/generators/json/sequence_diagram_generator.h b/src/sequence_diagram/generators/json/sequence_diagram_generator.h index bbf45078..e519f1bb 100644 --- a/src/sequence_diagram/generators/json/sequence_diagram_generator.h +++ b/src/sequence_diagram/generators/json/sequence_diagram_generator.h @@ -111,6 +111,8 @@ public: */ nlohmann::json ¤t_block_statement() const; + std::string make_display_name(const std::string &full_name) const; + private: /** * @brief Check if specified participant has already been generated. diff --git a/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.cc b/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.cc index b46bc00b..571eca2e 100644 --- a/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.cc +++ b/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.cc @@ -388,8 +388,10 @@ void generator::generate_participant( print_debug(class_participant, ostr); auto participant_name = - config().using_namespace().relative(config().simplify_template_type( - class_participant.full_name(false))); + config().simplify_template_type(class_participant.full_name(false)); + participant_name = + config().using_namespace().relative(participant_name); + common::ensure_lambda_type_is_relative(config(), participant_name); ostr << "participant \"" << render_name(participant_name) << "\" as " diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3ce15f5f..862b36cd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,7 +6,7 @@ file(GLOB_RECURSE TEST_CONFIG_YMLS test_config_data/*.yml test_compilation_database_data/*.yml test_compilation_database_data/*.json) -set(TEST_CASES_REQUIRING_CXX20 t00056 t00058 t00059 t00065 t00069) +set(TEST_CASES_REQUIRING_CXX20 t00056 t00058 t00059 t00065 t00069 t00074 t00075) set(TEST_CASES_REQUIRING_CXX20_MODULES t00070 t00071 t00072 t30012 t30013 t30014 t30015) set(TEST_CASES_REQUIRING_CUDA t20049 t20050 t20051) @@ -103,9 +103,9 @@ foreach(TEST_NAME ${TEST_NAMES}) ${TEST_CASE_MODULE_SOURCES}) endif(ENABLE_CXX_MODULES_TEST_CASES) target_sources(${TEST_NAME} PUBLIC ${TEST_NAME}.cc - ${TEST_CASE_SOURCES} catch.h) + ${TEST_CASE_SOURCES}) else() - target_sources(${TEST_NAME} PUBLIC ${TEST_NAME}.cc catch.h) + target_sources(${TEST_NAME} PUBLIC ${TEST_NAME}.cc) endif(TEST_NAME STREQUAL "test_cases") target_compile_features(${TEST_NAME} PRIVATE diff --git a/tests/catch.h b/tests/catch.h deleted file mode 100644 index 9cb6f4fe..00000000 --- a/tests/catch.h +++ /dev/null @@ -1,20325 +0,0 @@ -/* - * Catch v2.13.8 - * Generated: 2022-01-03 21:20:09.589503 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it - * directly Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -// start catch.hpp - -#define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 8 - -#ifdef __clang__ -#pragma clang system_header -#elif defined __GNUC__ -#pragma GCC system_header -#endif - -// start catch_suppress_warnings.h - -#ifdef __clang__ -#ifdef __ICC // icpc defines the __clang__ macro -#pragma warning(push) -#pragma warning(disable : 161 1682) -#else // __ICC -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#pragma clang diagnostic ignored "-Wswitch-enum" -#pragma clang diagnostic ignored "-Wcovered-switch-default" -#endif -#elif defined __GNUC__ -// Because REQUIREs trigger GCC's -Wparentheses, and because still -// supported version of g++ have only buggy support for _Pragmas, -// Wparentheses have to be suppressed globally. -#pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wpadded" -#endif -// end catch_suppress_warnings.h -#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -#define CATCH_IMPL -#define CATCH_CONFIG_ALL_PARTS -#endif - -// In the impl file, we want to have access to all parts of the headers -// Can also be used to sanely support PCHs -#if defined(CATCH_CONFIG_ALL_PARTS) -#define CATCH_CONFIG_EXTERNAL_INTERFACES -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) -#undef CATCH_CONFIG_DISABLE_MATCHERS -#endif -#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -#endif -#endif - -#if !defined(CATCH_CONFIG_IMPL_ONLY) -// start catch_platform.h - -// See e.g.: -// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html -#ifdef __APPLE__ -#include -#if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ - (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) -#define CATCH_PLATFORM_MAC -#elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) -#define CATCH_PLATFORM_IPHONE -#endif - -#elif defined(linux) || defined(__linux) || defined(__linux__) -#define CATCH_PLATFORM_LINUX - -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || \ - defined(_MSC_VER) || defined(__MINGW32__) -#define CATCH_PLATFORM_WINDOWS -#endif - -// end catch_platform.h - -#ifdef CATCH_IMPL -#ifndef CLARA_CONFIG_MAIN -#define CLARA_CONFIG_MAIN_NOT_DEFINED -#define CLARA_CONFIG_MAIN -#endif -#endif - -// start catch_user_interfaces.h - -namespace Catch { -unsigned int rngSeed(); -} - -// end catch_user_interfaces.h -// start catch_tag_alias_autoregistrar.h - -// start catch_common.h - -// start catch_compiler_capabilities.h - -// Detect a number of compiler features - by compiler -// The following features are defined: -// -// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? -// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? -// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? -// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? -// **************** -// Note to maintainers: if new toggles are added please document them -// in configuration.md, too -// **************** - -// In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -#ifdef __cplusplus - -#if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) -#define CATCH_CPP14_OR_GREATER -#endif - -#if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -#define CATCH_CPP17_OR_GREATER -#endif - -#endif - -// Only GCC compiler should be used in this block, so other compilers trying to -// mask themselves as GCC should be ignored. -#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && \ - !defined(__CUDACC__) && !defined(__LCC__) -#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma("GCC diagnostic push") -#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma("GCC diagnostic pop") - -#define CATCH_INTERNAL_IGNORE_BUT_WARN(...) \ - (void)__builtin_constant_p(__VA_ARGS__) - -#endif - -#if defined(__clang__) - -#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - _Pragma("clang diagnostic push") -#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma("clang diagnostic pop") - -// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug -// which results in calls to destructors being emitted for each temporary, -// without a matching initialization. In practice, this can result in something -// like `std::string::~string` being called on an uninitialized value. -// -// For example, this code will likely segfault under IBM XL: -// ``` -// REQUIRE(std::string("12") + "34" == "1234") -// ``` -// -// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. -#if !defined(__ibmxl__) && !defined(__CUDACC__) -#define CATCH_INTERNAL_IGNORE_BUT_WARN(...) \ - (void)__builtin_constant_p( \ - __VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, \ - hicpp-vararg) */ -#endif - -#define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \ - _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") - -#define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma("clang diagnostic ignored \"-Wparentheses\"") - -#define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma("clang diagnostic ignored \"-Wunused-variable\"") - -#define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma("clang diagnostic ignored " \ - "\"-Wgnu-zero-variadic-macro-arguments\"") - -#define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ - _Pragma("clang diagnostic ignored \"-Wunused-template\"") - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// Assume that non-Windows platforms support posix signals by default -#if !defined(CATCH_PLATFORM_WINDOWS) -#define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS -#endif - -//////////////////////////////////////////////////////////////////////////////// -// We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || \ - defined(__DJGPP__) -#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -#endif - -#ifdef __OS400__ -#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -#define CATCH_CONFIG_COLOUR_NONE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Android somehow still does not support std::to_string -#if defined(__ANDROID__) -#define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING -#define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Not all Windows environments support SEH properly -#if defined(__MINGW32__) -#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH -#endif - -//////////////////////////////////////////////////////////////////////////////// -// PS4 -#if defined(__ORBIS__) -#define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Cygwin -#ifdef __CYGWIN__ - -// Required for some versions of Cygwin to declare gettimeofday -// see: -// http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin -#define _BSD_SOURCE -// some versions of cygwin (most) do not support std::to_string. Use the libstd -// check. -// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html -// line 2812-2813 -#if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) && \ - !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) - -#define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING - -#endif -#endif // __CYGWIN__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#if defined(_MSC_VER) - -// Universal Windows platform does not support SEH -// Or console colours (or console at all...) -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -#define CATCH_CONFIG_COLOUR_NONE -#else -#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH -#endif - -#if !defined(__clang__) // Handle Clang masquerading for msvc - -// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ -// _MSVC_TRADITIONAL == 0 means new conformant preprocessor -// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -#if !defined(_MSVC_TRADITIONAL) || \ - (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -#define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#endif // MSVC_TRADITIONAL - -// Only do this if we're not using clang on Windows, which uses `diagnostic -// push` & `diagnostic pop` -#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma(warning(push)) -#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma(warning(pop)) -#endif // __clang__ - -#endif // _MSC_VER - -#if defined(_REENTRANT) || defined(_MSC_VER) -// Enable async processing, as -pthread is specified or no additional linking is -// required -#define CATCH_INTERNAL_CONFIG_USE_ASYNC -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// -// Check if we are compiled with -fno-exceptions or equivalent -#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) -#define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED -#endif - -//////////////////////////////////////////////////////////////////////////////// -// DJGPP -#ifdef __DJGPP__ -#define CATCH_INTERNAL_CONFIG_NO_WCHAR -#endif // __DJGPP__ - -//////////////////////////////////////////////////////////////////////////////// -// Embarcadero C++Build -#if defined(__BORLANDC__) -#define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// Use of __COUNTER__ is suppressed during code analysis in -// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly -// handled by it. -// Otherwise all supported compilers support COUNTER macro, -// but user still might want to turn it off -#if (!defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L) -#define CATCH_INTERNAL_CONFIG_COUNTER -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// RTX is a special version of Windows that is real time. -// This means that it is detected as Windows, but does not provide -// the same set of capabilities as real Windows does. -#if defined(UNDER_RTSS) || defined(RTX64_BUILD) -#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH -#define CATCH_INTERNAL_CONFIG_NO_ASYNC -#define CATCH_CONFIG_COLOUR_NONE -#endif - -#if !defined(_GLIBCXX_USE_C99_MATH_TR1) -#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER -#endif - -// Various stdlib support checks that require __has_include -#if defined(__has_include) -// Check if string_view is available and usable -#if __has_include() && defined(CATCH_CPP17_OR_GREATER) -#define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW -#endif - -// Check if optional is available and usable -#if __has_include() && defined(CATCH_CPP17_OR_GREATER) -#define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL -#endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - -// Check if byte is available and usable -#if __has_include() && defined(CATCH_CPP17_OR_GREATER) -#include -#if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) -#define CATCH_INTERNAL_CONFIG_CPP17_BYTE -#endif -#endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - -// Check if variant is available and usable -#if __has_include() && defined(CATCH_CPP17_OR_GREATER) -#if defined(__clang__) && (__clang_major__ < 8) -// work around clang bug with libstdc++ -// https://bugs.llvm.org/show_bug.cgi?id=31852 fix should be in clang 8, -// workaround in libstdc++ 8.2 -#include -#if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) -#define CATCH_CONFIG_NO_CPP17_VARIANT -#else -#define CATCH_INTERNAL_CONFIG_CPP17_VARIANT -#endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE - // < 9) -#else -#define CATCH_INTERNAL_CONFIG_CPP17_VARIANT -#endif // defined(__clang__) && (__clang_major__ < 8) -#endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // defined(__has_include) - -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && \ - !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) -#define CATCH_CONFIG_COUNTER -#endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && \ - !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && \ - !defined(CATCH_CONFIG_WINDOWS_SEH) && \ - !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) -#define CATCH_CONFIG_WINDOWS_SEH -#endif -// This is set by default, because we assume that unix compilers are -// posix-signal-compatible by default. -#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && \ - !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && \ - !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && \ - !defined(CATCH_CONFIG_POSIX_SIGNALS) -#define CATCH_CONFIG_POSIX_SIGNALS -#endif -// This is set by default, because we assume that compilers with no wchar_t -// support are just rare exceptions. -#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && \ - !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) -#define CATCH_CONFIG_WCHAR -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && \ - !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && \ - !defined(CATCH_CONFIG_CPP11_TO_STRING) -#define CATCH_CONFIG_CPP11_TO_STRING -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && \ - !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && \ - !defined(CATCH_CONFIG_CPP17_OPTIONAL) -#define CATCH_CONFIG_CPP17_OPTIONAL -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && \ - !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && \ - !defined(CATCH_CONFIG_CPP17_STRING_VIEW) -#define CATCH_CONFIG_CPP17_STRING_VIEW -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && \ - !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && \ - !defined(CATCH_CONFIG_CPP17_VARIANT) -#define CATCH_CONFIG_CPP17_VARIANT -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && \ - !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) -#define CATCH_CONFIG_CPP17_BYTE -#endif - -#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) -#define CATCH_INTERNAL_CONFIG_NEW_CAPTURE -#endif - -#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && \ - !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && \ - !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && \ - !defined(CATCH_CONFIG_NEW_CAPTURE) -#define CATCH_CONFIG_NEW_CAPTURE -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && \ - !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -#define CATCH_CONFIG_DISABLE_EXCEPTIONS -#endif - -#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && \ - !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && \ - !defined(CATCH_CONFIG_POLYFILL_ISNAN) -#define CATCH_CONFIG_POLYFILL_ISNAN -#endif - -#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && \ - !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && \ - !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) -#define CATCH_CONFIG_USE_ASYNC -#endif - -#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && \ - !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && \ - !defined(CATCH_CONFIG_ANDROID_LOGWRITE) -#define CATCH_CONFIG_ANDROID_LOGWRITE -#endif - -#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && \ - !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && \ - !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) -#define CATCH_CONFIG_GLOBAL_NEXTAFTER -#endif - -// Even if we do not think the compiler has that warning, we still have -// to provide a macro that can be used by the code. -#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) -#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION -#endif -#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) -#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) -#define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) -#define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) -#define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) -#define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS -#endif - -// The goal of this macro is to avoid evaluation of the arguments, but -// still have the compiler warn on problems inside... -#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) -#define CATCH_INTERNAL_IGNORE_BUT_WARN(...) -#endif - -#if defined(__APPLE__) && defined(__apple_build_version__) && \ - (__clang_major__ < 10) -#undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#elif defined(__clang__) && (__clang_major__ < 5) -#undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) -#define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -#define CATCH_TRY if ((true)) -#define CATCH_CATCH_ALL if ((false)) -#define CATCH_CATCH_ANON(type) if ((false)) -#else -#define CATCH_TRY try -#define CATCH_CATCH_ALL catch (...) -#define CATCH_CATCH_ANON(type) catch (type) -#endif - -#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && \ - !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && \ - !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) -#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#endif - -// end catch_compiler_capabilities.h -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2(name, line) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE(name, line) \ - INTERNAL_CATCH_UNIQUE_NAME_LINE2(name, line) -#ifdef CATCH_CONFIG_COUNTER -#define INTERNAL_CATCH_UNIQUE_NAME(name) \ - INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __COUNTER__) -#else -#define INTERNAL_CATCH_UNIQUE_NAME(name) \ - INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __LINE__) -#endif - -#include -#include -#include - -// We need a dummy global operator<< so we can bring it into Catch namespace -// later -struct Catch_global_namespace_dummy { }; -std::ostream &operator<<(std::ostream &, Catch_global_namespace_dummy); - -namespace Catch { - -struct CaseSensitive { - enum Choice { Yes, No }; -}; - -class NonCopyable { - NonCopyable(NonCopyable const &) = delete; - NonCopyable(NonCopyable &&) = delete; - NonCopyable &operator=(NonCopyable const &) = delete; - NonCopyable &operator=(NonCopyable &&) = delete; - -protected: - NonCopyable(); - virtual ~NonCopyable(); -}; - -struct SourceLineInfo { - - SourceLineInfo() = delete; - SourceLineInfo(char const *_file, std::size_t _line) noexcept - : file(_file) - , line(_line) - { - } - - SourceLineInfo(SourceLineInfo const &other) = default; - SourceLineInfo &operator=(SourceLineInfo const &) = default; - SourceLineInfo(SourceLineInfo &&) noexcept = default; - SourceLineInfo &operator=(SourceLineInfo &&) noexcept = default; - - bool empty() const noexcept { return file[0] == '\0'; } - bool operator==(SourceLineInfo const &other) const noexcept; - bool operator<(SourceLineInfo const &other) const noexcept; - - char const *file; - std::size_t line; -}; - -std::ostream &operator<<(std::ostream &os, SourceLineInfo const &info); - -// Bring in operator<< from global namespace into Catch namespace -// This is necessary because the overload of operator<< above makes -// lookup stop at namespace Catch -using ::operator<<; - -// Use this in variadic streaming macros to allow -// >> +StreamEndStop -// as well as -// >> stuff +StreamEndStop -struct StreamEndStop { - std::string operator+() const; -}; -template T const &operator+(T const &value, StreamEndStop) -{ - return value; -} -} - -#define CATCH_INTERNAL_LINEINFO \ - ::Catch::SourceLineInfo(__FILE__, static_cast(__LINE__)) - -// end catch_common.h -namespace Catch { - -struct RegistrarForTagAliases { - RegistrarForTagAliases( - char const *alias, char const *tag, SourceLineInfo const &lineInfo); -}; - -} // end namespace Catch - -#define CATCH_REGISTER_TAG_ALIAS(alias, spec) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace { \ - Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( \ - AutoRegisterTagAlias)(alias, spec, CATCH_INTERNAL_LINEINFO); \ - } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - -// end catch_tag_alias_autoregistrar.h -// start catch_test_registry.h - -// start catch_interfaces_testcase.h - -#include - -namespace Catch { - -class TestSpec; - -struct ITestInvoker { - virtual void invoke() const = 0; - virtual ~ITestInvoker(); -}; - -class TestCase; -struct IConfig; - -struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const &getAllTests() const = 0; - virtual std::vector const &getAllTestsSorted( - IConfig const &config) const = 0; -}; - -bool isThrowSafe(TestCase const &testCase, IConfig const &config); -bool matchTest( - TestCase const &testCase, TestSpec const &testSpec, IConfig const &config); -std::vector filterTests(std::vector const &testCases, - TestSpec const &testSpec, IConfig const &config); -std::vector const &getAllTestCasesSorted(IConfig const &config); - -} - -// end catch_interfaces_testcase.h -// start catch_stringref.h - -#include -#include -#include -#include - -namespace Catch { - -/// A non-owning string class (similar to the forthcoming std::string_view) -/// Note that, because a StringRef may be a substring of another string, -/// it may not be null terminated. -class StringRef { -public: - using size_type = std::size_t; - using const_iterator = const char *; - -private: - static constexpr char const *const s_empty = ""; - - char const *m_start = s_empty; - size_type m_size = 0; - -public: // construction - constexpr StringRef() noexcept = default; - - StringRef(char const *rawChars) noexcept; - - constexpr StringRef(char const *rawChars, size_type size) noexcept - : m_start(rawChars) - , m_size(size) - { - } - - StringRef(std::string const &stdString) noexcept - : m_start(stdString.c_str()) - , m_size(stdString.size()) - { - } - - explicit operator std::string() const - { - return std::string(m_start, m_size); - } - -public: // operators - auto operator==(StringRef const &other) const noexcept -> bool; - auto operator!=(StringRef const &other) const noexcept -> bool - { - return !(*this == other); - } - - auto operator[](size_type index) const noexcept -> char - { - assert(index < m_size); - return m_start[index]; - } - -public: // named queries - constexpr auto empty() const noexcept -> bool { return m_size == 0; } - constexpr auto size() const noexcept -> size_type { return m_size; } - - // Returns the current start pointer. If the StringRef is not - // null-terminated, throws std::domain_exception - auto c_str() const -> char const *; - -public: // substrings and searches - // Returns a substring of [start, start + length). - // If start + length > size(), then the substring is [start, size()). - // If start > size(), then the substring is empty. - auto substr(size_type start, size_type length) const noexcept -> StringRef; - - // Returns the current start pointer. May not be null-terminated. - auto data() const noexcept -> char const *; - - constexpr auto isNullTerminated() const noexcept -> bool - { - return m_start[m_size] == '\0'; - } - -public: // iterators - constexpr const_iterator begin() const { return m_start; } - constexpr const_iterator end() const { return m_start + m_size; } -}; - -auto operator+=(std::string &lhs, StringRef const &sr) -> std::string &; -auto operator<<(std::ostream &os, StringRef const &sr) -> std::ostream &; - -constexpr auto operator"" _sr(char const *rawChars, std::size_t size) noexcept - -> StringRef -{ - return StringRef(rawChars, size); -} -} // namespace Catch - -constexpr auto operator"" _catch_sr( - char const *rawChars, std::size_t size) noexcept -> Catch::StringRef -{ - return Catch::StringRef(rawChars, size); -} - -// end catch_stringref.h -// start catch_preprocessor.hpp - -#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ -#define CATCH_RECURSION_LEVEL1(...) \ - CATCH_RECURSION_LEVEL0( \ - CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL2(...) \ - CATCH_RECURSION_LEVEL1( \ - CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL3(...) \ - CATCH_RECURSION_LEVEL2( \ - CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL4(...) \ - CATCH_RECURSION_LEVEL3( \ - CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL5(...) \ - CATCH_RECURSION_LEVEL4( \ - CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) - -#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ -// MSVC needs more evaluations -#define CATCH_RECURSION_LEVEL6(...) \ - CATCH_RECURSION_LEVEL5( \ - CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) -#define CATCH_RECURSE(...) \ - CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) -#else -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) -#endif - -#define CATCH_REC_END(...) -#define CATCH_REC_OUT - -#define CATCH_EMPTY() -#define CATCH_DEFER(id) id CATCH_EMPTY() - -#define CATCH_REC_GET_END2() 0, CATCH_REC_END -#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 -#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 -#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT -#define CATCH_REC_NEXT1(test, next) CATCH_DEFER(CATCH_REC_NEXT0)(test, next, 0) -#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) - -#define CATCH_REC_LIST0(f, x, peek, ...) \ - , \ - f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1))( \ - f, peek, __VA_ARGS__) -#define CATCH_REC_LIST1(f, x, peek, ...) \ - , \ - f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST0))( \ - f, peek, __VA_ARGS__) -#define CATCH_REC_LIST2(f, x, peek, ...) \ - f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1))( \ - f, peek, __VA_ARGS__) - -#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) \ - , \ - f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD))( \ - f, userdata, peek, __VA_ARGS__) -#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) \ - , \ - f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD))( \ - f, userdata, peek, __VA_ARGS__) -#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) \ - f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD))( \ - f, userdata, peek, __VA_ARGS__) - -// Applies the function macro `f` to each of the remaining parameters, inserts -// commas between the results, and passes userdata as the first parameter to -// each invocation, e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), -// f(x, b), f(x, c) -#define CATCH_REC_LIST_UD(f, userdata, ...) \ - CATCH_RECURSE(CATCH_REC_LIST2_UD( \ - f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define CATCH_REC_LIST(f, ...) \ - CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) -#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO##__VA_ARGS__ -#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ -#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) \ - INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) -#else -// MSVC is adding extra space and needs another indirection to expand -// INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) -#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) \ - (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) -#endif - -#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ -#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) - -#define INTERNAL_CATCH_REMOVE_PARENS(...) \ - INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) - -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) \ - decltype(get_wrapper()) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) \ - INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) -#else -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - decltype(get_wrapper())) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) \ - INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2( \ - INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) -#endif - -#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...) \ - CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST, __VA_ARGS__) - -#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) -#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) \ - INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) -#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) \ - INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) -#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) \ - INTERNAL_CATCH_REMOVE_PARENS(_0), \ - INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) -#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) \ - INTERNAL_CATCH_REMOVE_PARENS(_0), \ - INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) -#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) \ - INTERNAL_CATCH_REMOVE_PARENS(_0), \ - INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) -#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) \ - INTERNAL_CATCH_REMOVE_PARENS(_0), \ - INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) -#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) \ - INTERNAL_CATCH_REMOVE_PARENS(_0), \ - INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) -#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) \ - INTERNAL_CATCH_REMOVE_PARENS(_0), \ - INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) -#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG( \ - _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ - INTERNAL_CATCH_REMOVE_PARENS(_0), \ - INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) -#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG( \ - _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ - INTERNAL_CATCH_REMOVE_PARENS(_0), \ - INTERNAL_CATCH_REMOVE_PARENS_10_ARG( \ - _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) - -#define INTERNAL_CATCH_VA_NARGS_IMPL( \ - _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) \ - N - -#define INTERNAL_CATCH_TYPE_GEN \ - template struct TypeList { }; \ - template \ - constexpr auto get_wrapper() noexcept -> TypeList \ - { \ - return {}; \ - } \ - template
(), - std::true_type()); - - template static auto test(...) -> std::false_type; - -public: - static const bool value = decltype(test(0))::value; -}; - -template std::string convertUnknownEnumToString(E e); - -template -typename std::enable_if::value && - !std::is_base_of::value, - std::string>::type -convertUnstreamable(T const &) -{ - return Detail::unprintableString; -} -template -typename std::enable_if::value && - std::is_base_of::value, - std::string>::type -convertUnstreamable(T const &ex) -{ - return ex.what(); -} - -template -typename std::enable_if::value, std::string>::type -convertUnstreamable(T const &value) -{ - return convertUnknownEnumToString(value); -} - -#if defined(_MANAGED) -//! Convert a CLR string to a utf8 std::string -template std::string clrReferenceToString(T ^ ref) -{ - if (ref == nullptr) - return std::string("null"); - auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); - cli::pin_ptr p = &bytes[0]; - return std::string(reinterpret_cast(p), bytes->Length); -} -#endif - -} // namespace Detail - -// If we decide for C++14, change these to enable_if_ts -template struct StringMaker { - template - static typename std::enable_if< - ::Catch::Detail::IsStreamInsertable::value, std::string>::type - convert(const Fake &value) - { - ReusableStringStream rss; - // NB: call using the function-like syntax to avoid ambiguity with - // user-defined templated operator<< under clang. - rss.operator<<(value); - return rss.str(); - } - - template - static typename std::enable_if< - !::Catch::Detail::IsStreamInsertable::value, std::string>::type - convert(const Fake &value) - { -#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) - return Detail::convertUnstreamable(value); -#else - return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); -#endif - } -}; - -namespace Detail { - -// This function dispatches all stringification requests inside of Catch. -// Should be preferably called fully qualified, like ::Catch::Detail::stringify -template std::string stringify(const T &e) -{ - return ::Catch::StringMaker::type>::type>::convert(e); -} - -template std::string convertUnknownEnumToString(E e) -{ - return ::Catch::Detail::stringify( - static_cast::type>(e)); -} - -#if defined(_MANAGED) -template std::string stringify(T ^ e) -{ - return ::Catch::StringMaker::convert(e); -} -#endif - -} // namespace Detail - -// Some predefined specializations - -template <> struct StringMaker { - static std::string convert(const std::string &str); -}; - -#ifdef CATCH_CONFIG_CPP17_STRING_VIEW -template <> struct StringMaker { - static std::string convert(std::string_view str); -}; -#endif - -template <> struct StringMaker { - static std::string convert(char const *str); -}; -template <> struct StringMaker { - static std::string convert(char *str); -}; - -#ifdef CATCH_CONFIG_WCHAR -template <> struct StringMaker { - static std::string convert(const std::wstring &wstr); -}; - -#ifdef CATCH_CONFIG_CPP17_STRING_VIEW -template <> struct StringMaker { - static std::string convert(std::wstring_view str); -}; -#endif - -template <> struct StringMaker { - static std::string convert(wchar_t const *str); -}; -template <> struct StringMaker { - static std::string convert(wchar_t *str); -}; -#endif - -// TBD: Should we use `strnlen` to ensure that we don't go out of the buffer, -// while keeping string semantics? -template struct StringMaker { - static std::string convert(char const *str) - { - return ::Catch::Detail::stringify(std::string{str}); - } -}; -template struct StringMaker { - static std::string convert(signed char const *str) - { - return ::Catch::Detail::stringify( - std::string{reinterpret_cast(str)}); - } -}; -template struct StringMaker { - static std::string convert(unsigned char const *str) - { - return ::Catch::Detail::stringify( - std::string{reinterpret_cast(str)}); - } -}; - -#if defined(CATCH_CONFIG_CPP17_BYTE) -template <> struct StringMaker { - static std::string convert(std::byte value); -}; -#endif // defined(CATCH_CONFIG_CPP17_BYTE) -template <> struct StringMaker { - static std::string convert(int value); -}; -template <> struct StringMaker { - static std::string convert(long value); -}; -template <> struct StringMaker { - static std::string convert(long long value); -}; -template <> struct StringMaker { - static std::string convert(unsigned int value); -}; -template <> struct StringMaker { - static std::string convert(unsigned long value); -}; -template <> struct StringMaker { - static std::string convert(unsigned long long value); -}; - -template <> struct StringMaker { - static std::string convert(bool b); -}; - -template <> struct StringMaker { - static std::string convert(char c); -}; -template <> struct StringMaker { - static std::string convert(signed char c); -}; -template <> struct StringMaker { - static std::string convert(unsigned char c); -}; - -template <> struct StringMaker { - static std::string convert(std::nullptr_t); -}; - -template <> struct StringMaker { - static std::string convert(float value); - static int precision; -}; - -template <> struct StringMaker { - static std::string convert(double value); - static int precision; -}; - -template struct StringMaker { - template static std::string convert(U *p) - { - if (p) { - return ::Catch::Detail::rawMemoryToString(p); - } - else { - return "nullptr"; - } - } -}; - -template struct StringMaker { - static std::string convert(R C::*p) - { - if (p) { - return ::Catch::Detail::rawMemoryToString(p); - } - else { - return "nullptr"; - } - } -}; - -#if defined(_MANAGED) -template struct StringMaker { - static std::string convert(T ^ ref) - { - return ::Catch::Detail::clrReferenceToString(ref); - } -}; -#endif - -namespace Detail { -template -std::string rangeToString(InputIterator first, Sentinel last) -{ - ReusableStringStream rss; - rss << "{ "; - if (first != last) { - rss << ::Catch::Detail::stringify(*first); - for (++first; first != last; ++first) - rss << ", " << ::Catch::Detail::stringify(*first); - } - rss << " }"; - return rss.str(); -} -} - -#ifdef __OBJC__ -template <> struct StringMaker { - static std::string convert(NSString *nsstring) - { - if (!nsstring) - return "nil"; - return std::string("@") + [nsstring UTF8String]; - } -}; -template <> struct StringMaker { - static std::string convert(NSObject *nsObject) - { - return ::Catch::Detail::stringify([nsObject description]); - } -}; -namespace Detail { -inline std::string stringify(NSString *nsstring) -{ - return StringMaker::convert(nsstring); -} - -} // namespace Detail -#endif // __OBJC__ - -} // namespace Catch - -////////////////////////////////////////////////////// -// Separate std-lib types stringification, so it can be selectively enabled -// This means that we do not bring in - -#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) -#define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER -#define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER -#define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER -#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -#define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER -#endif - -// Separate std::pair specialization -#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) -#include -namespace Catch { -template struct StringMaker> { - static std::string convert(const std::pair &pair) - { - ReusableStringStream rss; - rss << "{ " << ::Catch::Detail::stringify(pair.first) << ", " - << ::Catch::Detail::stringify(pair.second) << " }"; - return rss.str(); - } -}; -} -#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER - -#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && \ - defined(CATCH_CONFIG_CPP17_OPTIONAL) -#include -namespace Catch { -template struct StringMaker> { - static std::string convert(const std::optional &optional) - { - ReusableStringStream rss; - if (optional.has_value()) { - rss << ::Catch::Detail::stringify(*optional); - } - else { - rss << "{ }"; - } - return rss.str(); - } -}; -} -#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER - -// Separate std::tuple specialization -#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) -#include -namespace Catch { -namespace Detail { -template ::value)> -struct TupleElementPrinter { - static void print(const Tuple &tuple, std::ostream &os) - { - os << (N ? ", " : " ") - << ::Catch::Detail::stringify(std::get(tuple)); - TupleElementPrinter::print(tuple, os); - } -}; - -template -struct TupleElementPrinter { - static void print(const Tuple &, std::ostream &) { } -}; - -} - -template struct StringMaker> { - static std::string convert(const std::tuple &tuple) - { - ReusableStringStream rss; - rss << '{'; - Detail::TupleElementPrinter>::print( - tuple, rss.get()); - rss << " }"; - return rss.str(); - } -}; -} -#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER - -#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && \ - defined(CATCH_CONFIG_CPP17_VARIANT) -#include -namespace Catch { -template <> struct StringMaker { - static std::string convert(const std::monostate &) { return "{ }"; } -}; - -template struct StringMaker> { - static std::string convert(const std::variant &variant) - { - if (variant.valueless_by_exception()) { - return "{valueless variant}"; - } - else { - return std::visit( - [](const auto &value) { - return ::Catch::Detail::stringify(value); - }, - variant); - } - } -}; -} -#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER - -namespace Catch { -// Import begin/ end from std here -using std::begin; -using std::end; - -namespace detail { -template struct void_type { - using type = void; -}; - -template -struct is_range_impl : std::false_type { }; - -template -struct is_range_impl()))>::type> - : std::true_type { }; -} // namespace detail - -template struct is_range : detail::is_range_impl { }; - -#if defined(_MANAGED) // Managed types are never ranges -template struct is_range { - static const bool value = false; -}; -#endif - -template std::string rangeToString(Range const &range) -{ - return ::Catch::Detail::rangeToString(begin(range), end(range)); -} - -// Handle vector specially -template -std::string rangeToString(std::vector const &v) -{ - ReusableStringStream rss; - rss << "{ "; - bool first = true; - for (bool b : v) { - if (first) - first = false; - else - rss << ", "; - rss << ::Catch::Detail::stringify(b); - } - rss << " }"; - return rss.str(); -} - -template -struct StringMaker::value && - !::Catch::Detail::IsStreamInsertable::value>::type> { - static std::string convert(R const &range) { return rangeToString(range); } -}; - -template struct StringMaker { - static std::string convert(T const (&arr)[SZ]) - { - return rangeToString(arr); - } -}; - -} // namespace Catch - -// Separate std::chrono::duration specialization -#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -#include -#include -#include - -namespace Catch { - -template struct ratio_string { - static std::string symbol(); -}; - -template std::string ratio_string::symbol() -{ - Catch::ReusableStringStream rss; - rss << '[' << Ratio::num << '/' << Ratio::den << ']'; - return rss.str(); -} -template <> struct ratio_string { - static std::string symbol(); -}; -template <> struct ratio_string { - static std::string symbol(); -}; -template <> struct ratio_string { - static std::string symbol(); -}; -template <> struct ratio_string { - static std::string symbol(); -}; -template <> struct ratio_string { - static std::string symbol(); -}; -template <> struct ratio_string { - static std::string symbol(); -}; - -//////////// -// std::chrono::duration specializations -template -struct StringMaker> { - static std::string convert( - std::chrono::duration const &duration) - { - ReusableStringStream rss; - rss << duration.count() << ' ' << ratio_string::symbol() << 's'; - return rss.str(); - } -}; -template -struct StringMaker>> { - static std::string convert( - std::chrono::duration> const &duration) - { - ReusableStringStream rss; - rss << duration.count() << " s"; - return rss.str(); - } -}; -template -struct StringMaker>> { - static std::string convert( - std::chrono::duration> const &duration) - { - ReusableStringStream rss; - rss << duration.count() << " m"; - return rss.str(); - } -}; -template -struct StringMaker>> { - static std::string convert( - std::chrono::duration> const &duration) - { - ReusableStringStream rss; - rss << duration.count() << " h"; - return rss.str(); - } -}; - -//////////// -// std::chrono::time_point specialization -// Generic time_point cannot be specialized, only -// std::chrono::time_point -template -struct StringMaker> { - static std::string convert( - std::chrono::time_point const &time_point) - { - return ::Catch::Detail::stringify(time_point.time_since_epoch()) + - " since epoch"; - } -}; -// std::chrono::time_point specialization -template -struct StringMaker< - std::chrono::time_point> { - static std::string convert( - std::chrono::time_point const - &time_point) - { - auto converted = std::chrono::system_clock::to_time_t(time_point); - -#ifdef _MSC_VER - std::tm timeInfo = {}; - gmtime_s(&timeInfo, &converted); -#else - std::tm *timeInfo = std::gmtime(&converted); -#endif - - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - char timeStamp[timeStampSize]; - const char *const fmt = "%Y-%m-%dT%H:%M:%SZ"; - -#ifdef _MSC_VER - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); -#else - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); -#endif - return std::string(timeStamp); - } -}; -} -#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER - -#define INTERNAL_CATCH_REGISTER_ENUM(enumName, ...) \ - namespace Catch { \ - template <> struct StringMaker { \ - static std::string convert(enumName value) \ - { \ - static const auto &enumInfo = \ - ::Catch::getMutableRegistryHub() \ - .getMutableEnumValuesRegistry() \ - .registerEnum(#enumName, #__VA_ARGS__, {__VA_ARGS__}); \ - return static_cast( \ - enumInfo.lookup(static_cast(value))); \ - } \ - }; \ - } - -#define CATCH_REGISTER_ENUM(enumName, ...) \ - INTERNAL_CATCH_REGISTER_ENUM(enumName, __VA_ARGS__) - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -// end catch_tostring.h -#include - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4389) // '==' : signed/unsigned mismatch -#pragma warning(disable : 4018) // more "signed/unsigned mismatch" -#pragma warning(disable : 4312) // Converting int to T* using reinterpret_cast - // (issue on x64 platform) -#pragma warning( \ - disable : 4180) // qualifier applied to function type has no meaning -#pragma warning(disable : 4800) // Forcing result to true or false -#endif - -namespace Catch { - -struct ITransientExpression { - auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } - auto getResult() const -> bool { return m_result; } - virtual void streamReconstructedExpression(std::ostream &os) const = 0; - - ITransientExpression(bool isBinaryExpression, bool result) - : m_isBinaryExpression(isBinaryExpression) - , m_result(result) - { - } - - // We don't actually need a virtual destructor, but many static analysers - // complain if it's not here :-( - virtual ~ITransientExpression(); - - bool m_isBinaryExpression; - bool m_result; -}; - -void formatReconstructedExpression(std::ostream &os, std::string const &lhs, - StringRef op, std::string const &rhs); - -template -class BinaryExpr : public ITransientExpression { - LhsT m_lhs; - StringRef m_op; - RhsT m_rhs; - - void streamReconstructedExpression(std::ostream &os) const override - { - formatReconstructedExpression(os, Catch::Detail::stringify(m_lhs), m_op, - Catch::Detail::stringify(m_rhs)); - } - -public: - BinaryExpr(bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs) - : ITransientExpression{true, comparisonResult} - , m_lhs(lhs) - , m_op(op) - , m_rhs(rhs) - { - } - - template - auto operator&&(T) const -> BinaryExpr const - { - static_assert(always_false::value, - "chained comparisons are not supported inside assertions, " - "wrap the expression inside parentheses, or decompose it"); - } - - template - auto operator||(T) const -> BinaryExpr const - { - static_assert(always_false::value, - "chained comparisons are not supported inside assertions, " - "wrap the expression inside parentheses, or decompose it"); - } - - template - auto operator==(T) const -> BinaryExpr const - { - static_assert(always_false::value, - "chained comparisons are not supported inside assertions, " - "wrap the expression inside parentheses, or decompose it"); - } - - template - auto operator!=(T) const -> BinaryExpr const - { - static_assert(always_false::value, - "chained comparisons are not supported inside assertions, " - "wrap the expression inside parentheses, or decompose it"); - } - - template - auto operator>(T) const -> BinaryExpr const - { - static_assert(always_false::value, - "chained comparisons are not supported inside assertions, " - "wrap the expression inside parentheses, or decompose it"); - } - - template - auto operator<(T) const -> BinaryExpr const - { - static_assert(always_false::value, - "chained comparisons are not supported inside assertions, " - "wrap the expression inside parentheses, or decompose it"); - } - - template - auto operator>=(T) const -> BinaryExpr const - { - static_assert(always_false::value, - "chained comparisons are not supported inside assertions, " - "wrap the expression inside parentheses, or decompose it"); - } - - template - auto operator<=(T) const -> BinaryExpr const - { - static_assert(always_false::value, - "chained comparisons are not supported inside assertions, " - "wrap the expression inside parentheses, or decompose it"); - } -}; - -template class UnaryExpr : public ITransientExpression { - LhsT m_lhs; - - void streamReconstructedExpression(std::ostream &os) const override - { - os << Catch::Detail::stringify(m_lhs); - } - -public: - explicit UnaryExpr(LhsT lhs) - : ITransientExpression{false, static_cast(lhs)} - , m_lhs(lhs) - { - } -}; - -// Specialised comparison functions to handle equality comparisons between ints -// and pointers (NULL deduces as an int) -template -auto compareEqual(LhsT const &lhs, RhsT const &rhs) -> bool -{ - return static_cast(lhs == rhs); -} -template auto compareEqual(T *const &lhs, int rhs) -> bool -{ - return lhs == reinterpret_cast(rhs); -} -template auto compareEqual(T *const &lhs, long rhs) -> bool -{ - return lhs == reinterpret_cast(rhs); -} -template auto compareEqual(int lhs, T *const &rhs) -> bool -{ - return reinterpret_cast(lhs) == rhs; -} -template auto compareEqual(long lhs, T *const &rhs) -> bool -{ - return reinterpret_cast(lhs) == rhs; -} - -template -auto compareNotEqual(LhsT const &lhs, RhsT &&rhs) -> bool -{ - return static_cast(lhs != rhs); -} -template auto compareNotEqual(T *const &lhs, int rhs) -> bool -{ - return lhs != reinterpret_cast(rhs); -} -template auto compareNotEqual(T *const &lhs, long rhs) -> bool -{ - return lhs != reinterpret_cast(rhs); -} -template auto compareNotEqual(int lhs, T *const &rhs) -> bool -{ - return reinterpret_cast(lhs) != rhs; -} -template auto compareNotEqual(long lhs, T *const &rhs) -> bool -{ - return reinterpret_cast(lhs) != rhs; -} - -template class ExprLhs { - LhsT m_lhs; - -public: - explicit ExprLhs(LhsT lhs) - : m_lhs(lhs) - { - } - - template - auto operator==(RhsT const &rhs) -> BinaryExpr const - { - return {compareEqual(m_lhs, rhs), m_lhs, "==", rhs}; - } - auto operator==(bool rhs) -> BinaryExpr const - { - return {m_lhs == rhs, m_lhs, "==", rhs}; - } - - template - auto operator!=(RhsT const &rhs) -> BinaryExpr const - { - return {compareNotEqual(m_lhs, rhs), m_lhs, "!=", rhs}; - } - auto operator!=(bool rhs) -> BinaryExpr const - { - return {m_lhs != rhs, m_lhs, "!=", rhs}; - } - - template - auto operator>(RhsT const &rhs) -> BinaryExpr const - { - return {static_cast(m_lhs > rhs), m_lhs, ">", rhs}; - } - template - auto operator<(RhsT const &rhs) -> BinaryExpr const - { - return {static_cast(m_lhs < rhs), m_lhs, "<", rhs}; - } - template - auto operator>=(RhsT const &rhs) -> BinaryExpr const - { - return {static_cast(m_lhs >= rhs), m_lhs, ">=", rhs}; - } - template - auto operator<=(RhsT const &rhs) -> BinaryExpr const - { - return {static_cast(m_lhs <= rhs), m_lhs, "<=", rhs}; - } - template - auto operator|(RhsT const &rhs) -> BinaryExpr const - { - return {static_cast(m_lhs | rhs), m_lhs, "|", rhs}; - } - template - auto operator&(RhsT const &rhs) -> BinaryExpr const - { - return {static_cast(m_lhs & rhs), m_lhs, "&", rhs}; - } - template - auto operator^(RhsT const &rhs) -> BinaryExpr const - { - return {static_cast(m_lhs ^ rhs), m_lhs, "^", rhs}; - } - - template - auto operator&&(RhsT const &) -> BinaryExpr const - { - static_assert(always_false::value, - "operator&& is not supported inside assertions, " - "wrap the expression inside parentheses, or decompose it"); - } - - template - auto operator||(RhsT const &) -> BinaryExpr const - { - static_assert(always_false::value, - "operator|| is not supported inside assertions, " - "wrap the expression inside parentheses, or decompose it"); - } - - auto makeUnaryExpr() const -> UnaryExpr - { - return UnaryExpr{m_lhs}; - } -}; - -void handleExpression(ITransientExpression const &expr); - -template void handleExpression(ExprLhs const &expr) -{ - handleExpression(expr.makeUnaryExpr()); -} - -struct Decomposer { - template auto operator<=(T const &lhs) -> ExprLhs - { - return ExprLhs{lhs}; - } - - auto operator<=(bool value) -> ExprLhs - { - return ExprLhs{value}; - } -}; - -} // end namespace Catch - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -// end catch_decomposer.h -// start catch_interfaces_capture.h - -#include -#include - -namespace Catch { - -class AssertionResult; -struct AssertionInfo; -struct SectionInfo; -struct SectionEndInfo; -struct MessageInfo; -struct MessageBuilder; -struct Counts; -struct AssertionReaction; -struct SourceLineInfo; - -struct ITransientExpression; -struct IGeneratorTracker; - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -struct BenchmarkInfo; -template > -struct BenchmarkStats; -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - -struct IResultCapture { - - virtual ~IResultCapture(); - - virtual bool sectionStarted( - SectionInfo const §ionInfo, Counts &assertions) = 0; - virtual void sectionEnded(SectionEndInfo const &endInfo) = 0; - virtual void sectionEndedEarly(SectionEndInfo const &endInfo) = 0; - - virtual auto acquireGeneratorTracker(StringRef generatorName, - SourceLineInfo const &lineInfo) -> IGeneratorTracker & = 0; - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) - virtual void benchmarkPreparing(std::string const &name) = 0; - virtual void benchmarkStarting(BenchmarkInfo const &info) = 0; - virtual void benchmarkEnded(BenchmarkStats<> const &stats) = 0; - virtual void benchmarkFailed(std::string const &error) = 0; -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - - virtual void pushScopedMessage(MessageInfo const &message) = 0; - virtual void popScopedMessage(MessageInfo const &message) = 0; - - virtual void emplaceUnscopedMessage(MessageBuilder const &builder) = 0; - - virtual void handleFatalErrorCondition(StringRef message) = 0; - - virtual void handleExpr(AssertionInfo const &info, - ITransientExpression const &expr, AssertionReaction &reaction) = 0; - virtual void handleMessage(AssertionInfo const &info, - ResultWas::OfType resultType, StringRef const &message, - AssertionReaction &reaction) = 0; - virtual void handleUnexpectedExceptionNotThrown( - AssertionInfo const &info, AssertionReaction &reaction) = 0; - virtual void handleUnexpectedInflightException(AssertionInfo const &info, - std::string const &message, AssertionReaction &reaction) = 0; - virtual void handleIncomplete(AssertionInfo const &info) = 0; - virtual void handleNonExpr(AssertionInfo const &info, - ResultWas::OfType resultType, AssertionReaction &reaction) = 0; - - virtual bool lastAssertionPassed() = 0; - virtual void assertionPassed() = 0; - - // Deprecated, do not use: - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult *getLastResult() const = 0; - virtual void exceptionEarlyReported() = 0; -}; - -IResultCapture &getResultCapture(); -} - -// end catch_interfaces_capture.h -namespace Catch { - -struct TestFailureException { }; -struct AssertionResultData; -struct IResultCapture; -class RunContext; - -class LazyExpression { - friend class AssertionHandler; - friend struct AssertionStats; - friend class RunContext; - - ITransientExpression const *m_transientExpression = nullptr; - bool m_isNegated; - -public: - LazyExpression(bool isNegated); - LazyExpression(LazyExpression const &other); - LazyExpression &operator=(LazyExpression const &) = delete; - - explicit operator bool() const; - - friend auto operator<<(std::ostream &os, LazyExpression const &lazyExpr) - -> std::ostream &; -}; - -struct AssertionReaction { - bool shouldDebugBreak = false; - bool shouldThrow = false; -}; - -class AssertionHandler { - AssertionInfo m_assertionInfo; - AssertionReaction m_reaction; - bool m_completed = false; - IResultCapture &m_resultCapture; - -public: - AssertionHandler(StringRef const ¯oName, SourceLineInfo const &lineInfo, - StringRef capturedExpression, - ResultDisposition::Flags resultDisposition); - ~AssertionHandler() - { - if (!m_completed) { - m_resultCapture.handleIncomplete(m_assertionInfo); - } - } - - template void handleExpr(ExprLhs const &expr) - { - handleExpr(expr.makeUnaryExpr()); - } - void handleExpr(ITransientExpression const &expr); - - void handleMessage(ResultWas::OfType resultType, StringRef const &message); - - void handleExceptionThrownAsExpected(); - void handleUnexpectedExceptionNotThrown(); - void handleExceptionNotThrownAsExpected(); - void handleThrowingCallSkipped(); - void handleUnexpectedInflightException(); - - void complete(); - void setCompleted(); - - // query - auto allowThrows() const -> bool; -}; - -void handleExceptionMatchExpr(AssertionHandler &handler, std::string const &str, - StringRef const &matcherString); - -} // namespace Catch - -// end catch_assertionhandler.h -// start catch_message.h - -#include -#include - -namespace Catch { - -struct MessageInfo { - MessageInfo(StringRef const &_macroName, SourceLineInfo const &_lineInfo, - ResultWas::OfType _type); - - StringRef macroName; - std::string message; - SourceLineInfo lineInfo; - ResultWas::OfType type; - unsigned int sequence; - - bool operator==(MessageInfo const &other) const; - bool operator<(MessageInfo const &other) const; - -private: - static unsigned int globalCount; -}; - -struct MessageStream { - - template MessageStream &operator<<(T const &value) - { - m_stream << value; - return *this; - } - - ReusableStringStream m_stream; -}; - -struct MessageBuilder : MessageStream { - MessageBuilder(StringRef const ¯oName, SourceLineInfo const &lineInfo, - ResultWas::OfType type); - - template MessageBuilder &operator<<(T const &value) - { - m_stream << value; - return *this; - } - - MessageInfo m_info; -}; - -class ScopedMessage { -public: - explicit ScopedMessage(MessageBuilder const &builder); - ScopedMessage(ScopedMessage &duplicate) = delete; - ScopedMessage(ScopedMessage &&old); - ~ScopedMessage(); - - MessageInfo m_info; - bool m_moved; -}; - -class Capturer { - std::vector m_messages; - IResultCapture &m_resultCapture = getResultCapture(); - size_t m_captured = 0; - -public: - Capturer(StringRef macroName, SourceLineInfo const &lineInfo, - ResultWas::OfType resultType, StringRef names); - ~Capturer(); - - void captureValue(size_t index, std::string const &value); - - template void captureValues(size_t index, T const &value) - { - captureValue(index, Catch::Detail::stringify(value)); - } - - template - void captureValues(size_t index, T const &value, Ts const &...values) - { - captureValue(index, Catch::Detail::stringify(value)); - captureValues(index + 1, values...); - } -}; - -} // end namespace Catch - -// end catch_message.h -#if !defined(CATCH_CONFIG_DISABLE) - -#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) -#define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ -#else -#define CATCH_INTERNAL_STRINGIFY(...) \ - "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" -#endif - -#if defined(CATCH_CONFIG_FAST_COMPILE) || \ - defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - -/////////////////////////////////////////////////////////////////////////////// -// Another way to speed-up compilation is to omit local try-catch for REQUIRE* -// macros. -#define INTERNAL_CATCH_TRY -#define INTERNAL_CATCH_CATCH(capturer) - -#else // CATCH_CONFIG_FAST_COMPILE - -#define INTERNAL_CATCH_TRY try -#define INTERNAL_CATCH_CATCH(handler) \ - catch (...) \ - { \ - handler.handleUnexpectedInflightException(); \ - } - -#endif - -#define INTERNAL_CATCH_REACT(handler) handler.complete(); - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST(macroName, resultDisposition, ...) \ - do { \ - CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \ - Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, \ - CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), \ - resultDisposition); \ - INTERNAL_CATCH_TRY \ - { \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - catchAssertionHandler.handleExpr( \ - Catch::Decomposer() <= __VA_ARGS__); \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - } \ - INTERNAL_CATCH_CATCH(catchAssertionHandler) \ - INTERNAL_CATCH_REACT(catchAssertionHandler) \ - } while ((void)0, (false) && static_cast(!!(__VA_ARGS__))) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF(macroName, resultDisposition, ...) \ - INTERNAL_CATCH_TEST(macroName, resultDisposition, __VA_ARGS__); \ - if (Catch::getResultCapture().lastAssertionPassed()) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE(macroName, resultDisposition, ...) \ - INTERNAL_CATCH_TEST(macroName, resultDisposition, __VA_ARGS__); \ - if (!Catch::getResultCapture().lastAssertionPassed()) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW(macroName, resultDisposition, ...) \ - do { \ - Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, \ - CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), \ - resultDisposition); \ - try { \ - static_cast(__VA_ARGS__); \ - catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ - } \ - catch (...) { \ - catchAssertionHandler.handleUnexpectedInflightException(); \ - } \ - INTERNAL_CATCH_REACT(catchAssertionHandler) \ - } while (false) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS(macroName, resultDisposition, ...) \ - do { \ - Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, \ - CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), \ - resultDisposition); \ - if (catchAssertionHandler.allowThrows()) \ - try { \ - static_cast(__VA_ARGS__); \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch (...) { \ - catchAssertionHandler.handleExceptionThrownAsExpected(); \ - } \ - else \ - catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT(catchAssertionHandler) \ - } while (false) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_AS( \ - macroName, exceptionType, resultDisposition, expr) \ - do { \ - Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, \ - CATCH_INTERNAL_LINEINFO, \ - CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY( \ - exceptionType), \ - resultDisposition); \ - if (catchAssertionHandler.allowThrows()) \ - try { \ - static_cast(expr); \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch (exceptionType const &) { \ - catchAssertionHandler.handleExceptionThrownAsExpected(); \ - } \ - catch (...) { \ - catchAssertionHandler.handleUnexpectedInflightException(); \ - } \ - else \ - catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT(catchAssertionHandler) \ - } while (false) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_MSG(macroName, messageType, resultDisposition, ...) \ - do { \ - Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, \ - CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition); \ - catchAssertionHandler.handleMessage(messageType, \ - (Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop()) \ - .m_stream.str()); \ - INTERNAL_CATCH_REACT(catchAssertionHandler) \ - } while (false) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_CAPTURE(varName, macroName, ...) \ - auto varName = Catch::Capturer(macroName, CATCH_INTERNAL_LINEINFO, \ - Catch::ResultWas::Info, #__VA_ARGS__); \ - varName.captureValues(0, __VA_ARGS__) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_INFO(macroName, log) \ - Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME(scopedMessage)( \ - Catch::MessageBuilder(macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \ - Catch::ResultWas::Info) \ - << log); - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_UNSCOPED_INFO(macroName, log) \ - Catch::getResultCapture().emplaceUnscopedMessage( \ - Catch::MessageBuilder(macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \ - Catch::ResultWas::Info) \ - << log) - -/////////////////////////////////////////////////////////////////////////////// -// Although this is matcher-based, it can be used with just a string -#define INTERNAL_CATCH_THROWS_STR_MATCHES( \ - macroName, resultDisposition, matcher, ...) \ - do { \ - Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, \ - CATCH_INTERNAL_LINEINFO, \ - CATCH_INTERNAL_STRINGIFY( \ - __VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), \ - resultDisposition); \ - if (catchAssertionHandler.allowThrows()) \ - try { \ - static_cast(__VA_ARGS__); \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch (...) { \ - Catch::handleExceptionMatchExpr( \ - catchAssertionHandler, matcher, #matcher##_catch_sr); \ - } \ - else \ - catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT(catchAssertionHandler) \ - } while (false) - -#endif // CATCH_CONFIG_DISABLE - -// end catch_capture.hpp -// start catch_section.h - -// start catch_section_info.h - -// start catch_totals.h - -#include - -namespace Catch { - -struct Counts { - Counts operator-(Counts const &other) const; - Counts &operator+=(Counts const &other); - - std::size_t total() const; - bool allPassed() const; - bool allOk() const; - - std::size_t passed = 0; - std::size_t failed = 0; - std::size_t failedButOk = 0; -}; - -struct Totals { - - Totals operator-(Totals const &other) const; - Totals &operator+=(Totals const &other); - - Totals delta(Totals const &prevTotals) const; - - int error = 0; - Counts assertions; - Counts testCases; -}; -} - -// end catch_totals.h -#include - -namespace Catch { - -struct SectionInfo { - SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name); - - // Deprecated - SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name, - std::string const &) - : SectionInfo(_lineInfo, _name) - { - } - - std::string name; - std::string description; // !Deprecated: this will always be empty - SourceLineInfo lineInfo; -}; - -struct SectionEndInfo { - SectionInfo sectionInfo; - Counts prevAssertions; - double durationInSeconds; -}; - -} // end namespace Catch - -// end catch_section_info.h -// start catch_timer.h - -#include - -namespace Catch { - -auto getCurrentNanosecondsSinceEpoch() -> uint64_t; -auto getEstimatedClockResolution() -> uint64_t; - -class Timer { - uint64_t m_nanoseconds = 0; - -public: - void start(); - auto getElapsedNanoseconds() const -> uint64_t; - auto getElapsedMicroseconds() const -> uint64_t; - auto getElapsedMilliseconds() const -> unsigned int; - auto getElapsedSeconds() const -> double; -}; - -} // namespace Catch - -// end catch_timer.h -#include - -namespace Catch { - -class Section : NonCopyable { -public: - Section(SectionInfo const &info); - ~Section(); - - // This indicates whether the section should be executed or not - explicit operator bool() const; - -private: - SectionInfo m_info; - - std::string m_name; - Counts m_assertions; - bool m_sectionIncluded; - Timer m_timer; -}; - -} // end namespace Catch - -#define INTERNAL_CATCH_SECTION(...) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - if (Catch::Section const &INTERNAL_CATCH_UNIQUE_NAME( \ - catch_internal_Section) = \ - Catch::SectionInfo(CATCH_INTERNAL_LINEINFO, __VA_ARGS__)) \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - -#define INTERNAL_CATCH_DYNAMIC_SECTION(...) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - if (Catch::Section const &INTERNAL_CATCH_UNIQUE_NAME( \ - catch_internal_Section) = \ - Catch::SectionInfo(CATCH_INTERNAL_LINEINFO, \ - (Catch::ReusableStringStream() << __VA_ARGS__).str())) \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - -// end catch_section.h -// start catch_interfaces_exception.h - -// start catch_interfaces_registry_hub.h - -#include -#include - -namespace Catch { - -class TestCase; -struct ITestCaseRegistry; -struct IExceptionTranslatorRegistry; -struct IExceptionTranslator; -struct IReporterRegistry; -struct IReporterFactory; -struct ITagAliasRegistry; -struct IMutableEnumValuesRegistry; - -class StartupExceptionRegistry; - -using IReporterFactoryPtr = std::shared_ptr; - -struct IRegistryHub { - virtual ~IRegistryHub(); - - virtual IReporterRegistry const &getReporterRegistry() const = 0; - virtual ITestCaseRegistry const &getTestCaseRegistry() const = 0; - virtual ITagAliasRegistry const &getTagAliasRegistry() const = 0; - virtual IExceptionTranslatorRegistry const & - getExceptionTranslatorRegistry() const = 0; - - virtual StartupExceptionRegistry const & - getStartupExceptionRegistry() const = 0; -}; - -struct IMutableRegistryHub { - virtual ~IMutableRegistryHub(); - virtual void registerReporter( - std::string const &name, IReporterFactoryPtr const &factory) = 0; - virtual void registerListener(IReporterFactoryPtr const &factory) = 0; - virtual void registerTest(TestCase const &testInfo) = 0; - virtual void registerTranslator(const IExceptionTranslator *translator) = 0; - virtual void registerTagAlias(std::string const &alias, - std::string const &tag, SourceLineInfo const &lineInfo) = 0; - virtual void registerStartupException() noexcept = 0; - virtual IMutableEnumValuesRegistry &getMutableEnumValuesRegistry() = 0; -}; - -IRegistryHub const &getRegistryHub(); -IMutableRegistryHub &getMutableRegistryHub(); -void cleanUp(); -std::string translateActiveException(); - -} - -// end catch_interfaces_registry_hub.h -#if defined(CATCH_CONFIG_DISABLE) -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG(translatorName, signature) \ - static std::string translatorName(signature) -#endif - -#include -#include -#include - -namespace Catch { -using exceptionTranslateFunction = std::string (*)(); - -struct IExceptionTranslator; -using ExceptionTranslators = - std::vector>; - -struct IExceptionTranslator { - virtual ~IExceptionTranslator(); - virtual std::string translate(ExceptionTranslators::const_iterator it, - ExceptionTranslators::const_iterator itEnd) const = 0; -}; - -struct IExceptionTranslatorRegistry { - virtual ~IExceptionTranslatorRegistry(); - - virtual std::string translateActiveException() const = 0; -}; - -class ExceptionTranslatorRegistrar { - template - class ExceptionTranslator : public IExceptionTranslator { - public: - ExceptionTranslator(std::string (*translateFunction)(T &)) - : m_translateFunction(translateFunction) - { - } - - std::string translate(ExceptionTranslators::const_iterator it, - ExceptionTranslators::const_iterator itEnd) const override - { -#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - return ""; -#else - try { - if (it == itEnd) - std::rethrow_exception(std::current_exception()); - else - return (*it)->translate(it + 1, itEnd); - } - catch (T &ex) { - return m_translateFunction(ex); - } -#endif - } - - protected: - std::string (*m_translateFunction)(T &); - }; - -public: - template - ExceptionTranslatorRegistrar(std::string (*translateFunction)(T &)) - { - getMutableRegistryHub().registerTranslator( - new ExceptionTranslator(translateFunction)); - } -}; -} - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2(translatorName, signature) \ - static std::string translatorName(signature); \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace { \ - Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( \ - catch_internal_ExceptionRegistrar)(&translatorName); \ - } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - static std::string translatorName(signature) - -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION(signature) \ - INTERNAL_CATCH_TRANSLATE_EXCEPTION2( \ - INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionTranslator), \ - signature) - -// end catch_interfaces_exception.h -// start catch_approx.h - -#include - -namespace Catch { -namespace Detail { - -class Approx { -private: - bool equalityComparisonImpl(double other) const; - // Validates the new margin (margin >= 0) - // out-of-line to avoid including stdexcept in the header - void setMargin(double margin); - // Validates the new epsilon (0 < epsilon < 1) - // out-of-line to avoid including stdexcept in the header - void setEpsilon(double epsilon); - -public: - explicit Approx(double value); - - static Approx custom(); - - Approx operator-() const; - - template ::value>::type> - Approx operator()(T const &value) const - { - Approx approx(static_cast(value)); - approx.m_epsilon = m_epsilon; - approx.m_margin = m_margin; - approx.m_scale = m_scale; - return approx; - } - - template ::value>::type> - explicit Approx(T const &value) - : Approx(static_cast(value)) - { - } - - template ::value>::type> - friend bool operator==(const T &lhs, Approx const &rhs) - { - auto lhs_v = static_cast(lhs); - return rhs.equalityComparisonImpl(lhs_v); - } - - template ::value>::type> - friend bool operator==(Approx const &lhs, const T &rhs) - { - return operator==(rhs, lhs); - } - - template ::value>::type> - friend bool operator!=(T const &lhs, Approx const &rhs) - { - return !operator==(lhs, rhs); - } - - template ::value>::type> - friend bool operator!=(Approx const &lhs, T const &rhs) - { - return !operator==(rhs, lhs); - } - - template ::value>::type> - friend bool operator<=(T const &lhs, Approx const &rhs) - { - return static_cast(lhs) < rhs.m_value || lhs == rhs; - } - - template ::value>::type> - friend bool operator<=(Approx const &lhs, T const &rhs) - { - return lhs.m_value < static_cast(rhs) || lhs == rhs; - } - - template ::value>::type> - friend bool operator>=(T const &lhs, Approx const &rhs) - { - return static_cast(lhs) > rhs.m_value || lhs == rhs; - } - - template ::value>::type> - friend bool operator>=(Approx const &lhs, T const &rhs) - { - return lhs.m_value > static_cast(rhs) || lhs == rhs; - } - - template ::value>::type> - Approx &epsilon(T const &newEpsilon) - { - double epsilonAsDouble = static_cast(newEpsilon); - setEpsilon(epsilonAsDouble); - return *this; - } - - template ::value>::type> - Approx &margin(T const &newMargin) - { - double marginAsDouble = static_cast(newMargin); - setMargin(marginAsDouble); - return *this; - } - - template ::value>::type> - Approx &scale(T const &newScale) - { - m_scale = static_cast(newScale); - return *this; - } - - std::string toString() const; - -private: - double m_epsilon; - double m_margin; - double m_scale; - double m_value; -}; -} // end namespace Detail - -namespace literals { -Detail::Approx operator"" _a(long double val); -Detail::Approx operator"" _a(unsigned long long val); -} // end namespace literals - -template <> struct StringMaker { - static std::string convert(Catch::Detail::Approx const &value); -}; - -} // end namespace Catch - -// end catch_approx.h -// start catch_string_manip.h - -#include -#include -#include - -namespace Catch { - -bool startsWith(std::string const &s, std::string const &prefix); -bool startsWith(std::string const &s, char prefix); -bool endsWith(std::string const &s, std::string const &suffix); -bool endsWith(std::string const &s, char suffix); -bool contains(std::string const &s, std::string const &infix); -void toLowerInPlace(std::string &s); -std::string toLower(std::string const &s); -//! Returns a new string without whitespace at the start/end -std::string trim(std::string const &str); -//! Returns a substring of the original ref without whitespace. Beware -//! lifetimes! -StringRef trim(StringRef ref); - -// !!! Be aware, returns refs into original string - make sure original string -// outlives them -std::vector splitStringRef(StringRef str, char delimiter); -bool replaceInPlace(std::string &str, std::string const &replaceThis, - std::string const &withThis); - -struct pluralise { - pluralise(std::size_t count, std::string const &label); - - friend std::ostream &operator<<( - std::ostream &os, pluralise const &pluraliser); - - std::size_t m_count; - std::string m_label; -}; -} - -// end catch_string_manip.h -#ifndef CATCH_CONFIG_DISABLE_MATCHERS -// start catch_capture_matchers.h - -// start catch_matchers.h - -#include -#include - -namespace Catch { -namespace Matchers { -namespace Impl { - -template struct MatchAllOf; -template struct MatchAnyOf; -template struct MatchNotOf; - -class MatcherUntypedBase { -public: - MatcherUntypedBase() = default; - MatcherUntypedBase(MatcherUntypedBase const &) = default; - MatcherUntypedBase &operator=(MatcherUntypedBase const &) = delete; - std::string toString() const; - -protected: - virtual ~MatcherUntypedBase(); - virtual std::string describe() const = 0; - mutable std::string m_cachedToString; -}; - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wnon-virtual-dtor" -#endif - -template struct MatcherMethod { - virtual bool match(ObjectT const &arg) const = 0; -}; - -#if defined(__OBJC__) -// Hack to fix Catch GH issue #1661. Could use id for generic Object support. -// use of const for Object pointers is very uncommon and under ARC it causes -// some kind of signature mismatch that breaks compilation -template <> struct MatcherMethod { - virtual bool match(NSString *arg) const = 0; -}; -#endif - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -template -struct MatcherBase : MatcherUntypedBase, MatcherMethod { - - MatchAllOf operator&&(MatcherBase const &other) const; - MatchAnyOf operator||(MatcherBase const &other) const; - MatchNotOf operator!() const; -}; - -template struct MatchAllOf : MatcherBase { - bool match(ArgT const &arg) const override - { - for (auto matcher : m_matchers) { - if (!matcher->match(arg)) - return false; - } - return true; - } - std::string describe() const override - { - std::string description; - description.reserve(4 + m_matchers.size() * 32); - description += "( "; - bool first = true; - for (auto matcher : m_matchers) { - if (first) - first = false; - else - description += " and "; - description += matcher->toString(); - } - description += " )"; - return description; - } - - MatchAllOf operator&&(MatcherBase const &other) - { - auto copy(*this); - copy.m_matchers.push_back(&other); - return copy; - } - - std::vector const *> m_matchers; -}; -template struct MatchAnyOf : MatcherBase { - - bool match(ArgT const &arg) const override - { - for (auto matcher : m_matchers) { - if (matcher->match(arg)) - return true; - } - return false; - } - std::string describe() const override - { - std::string description; - description.reserve(4 + m_matchers.size() * 32); - description += "( "; - bool first = true; - for (auto matcher : m_matchers) { - if (first) - first = false; - else - description += " or "; - description += matcher->toString(); - } - description += " )"; - return description; - } - - MatchAnyOf operator||(MatcherBase const &other) - { - auto copy(*this); - copy.m_matchers.push_back(&other); - return copy; - } - - std::vector const *> m_matchers; -}; - -template struct MatchNotOf : MatcherBase { - - MatchNotOf(MatcherBase const &underlyingMatcher) - : m_underlyingMatcher(underlyingMatcher) - { - } - - bool match(ArgT const &arg) const override - { - return !m_underlyingMatcher.match(arg); - } - - std::string describe() const override - { - return "not " + m_underlyingMatcher.toString(); - } - MatcherBase const &m_underlyingMatcher; -}; - -template -MatchAllOf MatcherBase::operator&&(MatcherBase const &other) const -{ - return MatchAllOf() && *this && other; -} -template -MatchAnyOf MatcherBase::operator||(MatcherBase const &other) const -{ - return MatchAnyOf() || *this || other; -} -template MatchNotOf MatcherBase::operator!() const -{ - return MatchNotOf(*this); -} - -} // namespace Impl - -} // namespace Matchers - -using namespace Matchers; -using Matchers::Impl::MatcherBase; - -} // namespace Catch - -// end catch_matchers.h -// start catch_matchers_exception.hpp - -namespace Catch { -namespace Matchers { -namespace Exception { - -class ExceptionMessageMatcher : public MatcherBase { - std::string m_message; - -public: - ExceptionMessageMatcher(std::string const &message) - : m_message(message) - { - } - - bool match(std::exception const &ex) const override; - - std::string describe() const override; -}; - -} // namespace Exception - -Exception::ExceptionMessageMatcher Message(std::string const &message); - -} // namespace Matchers -} // namespace Catch - -// end catch_matchers_exception.hpp -// start catch_matchers_floating.h - -namespace Catch { -namespace Matchers { - -namespace Floating { - -enum class FloatingPointKind : uint8_t; - -struct WithinAbsMatcher : MatcherBase { - WithinAbsMatcher(double target, double margin); - bool match(double const &matchee) const override; - std::string describe() const override; - -private: - double m_target; - double m_margin; -}; - -struct WithinUlpsMatcher : MatcherBase { - WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType); - bool match(double const &matchee) const override; - std::string describe() const override; - -private: - double m_target; - uint64_t m_ulps; - FloatingPointKind m_type; -}; - -// Given IEEE-754 format for floats and doubles, we can assume -// that float -> double promotion is lossless. Given this, we can -// assume that if we do the standard relative comparison of -// |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get -// the same result if we do this for floats, as if we do this for -// doubles that were promoted from floats. -struct WithinRelMatcher : MatcherBase { - WithinRelMatcher(double target, double epsilon); - bool match(double const &matchee) const override; - std::string describe() const override; - -private: - double m_target; - double m_epsilon; -}; - -} // namespace Floating - -// The following functions create the actual matcher objects. -// This allows the types to be inferred -Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); -Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); -Floating::WithinAbsMatcher WithinAbs(double target, double margin); -Floating::WithinRelMatcher WithinRel(double target, double eps); -// defaults epsilon to 100*numeric_limits::epsilon() -Floating::WithinRelMatcher WithinRel(double target); -Floating::WithinRelMatcher WithinRel(float target, float eps); -// defaults epsilon to 100*numeric_limits::epsilon() -Floating::WithinRelMatcher WithinRel(float target); - -} // namespace Matchers -} // namespace Catch - -// end catch_matchers_floating.h -// start catch_matchers_generic.hpp - -#include -#include - -namespace Catch { -namespace Matchers { -namespace Generic { - -namespace Detail { -std::string finalizeDescription(const std::string &desc); -} - -template class PredicateMatcher : public MatcherBase { - std::function m_predicate; - std::string m_description; - -public: - PredicateMatcher( - std::function const &elem, std::string const &descr) - : m_predicate(std::move(elem)) - , m_description(Detail::finalizeDescription(descr)) - { - } - - bool match(T const &item) const override { return m_predicate(item); } - - std::string describe() const override { return m_description; } -}; - -} // namespace Generic - -// The following functions create the actual matcher objects. -// The user has to explicitly specify type to the function, because -// inferring std::function is hard (but possible) and -// requires a lot of TMP. -template -Generic::PredicateMatcher Predicate( - std::function const &predicate, - std::string const &description = "") -{ - return Generic::PredicateMatcher(predicate, description); -} - -} // namespace Matchers -} // namespace Catch - -// end catch_matchers_generic.hpp -// start catch_matchers_string.h - -#include - -namespace Catch { -namespace Matchers { - -namespace StdString { - -struct CasedString { - CasedString(std::string const &str, CaseSensitive::Choice caseSensitivity); - std::string adjustString(std::string const &str) const; - std::string caseSensitivitySuffix() const; - - CaseSensitive::Choice m_caseSensitivity; - std::string m_str; -}; - -struct StringMatcherBase : MatcherBase { - StringMatcherBase( - std::string const &operation, CasedString const &comparator); - std::string describe() const override; - - CasedString m_comparator; - std::string m_operation; -}; - -struct EqualsMatcher : StringMatcherBase { - EqualsMatcher(CasedString const &comparator); - bool match(std::string const &source) const override; -}; -struct ContainsMatcher : StringMatcherBase { - ContainsMatcher(CasedString const &comparator); - bool match(std::string const &source) const override; -}; -struct StartsWithMatcher : StringMatcherBase { - StartsWithMatcher(CasedString const &comparator); - bool match(std::string const &source) const override; -}; -struct EndsWithMatcher : StringMatcherBase { - EndsWithMatcher(CasedString const &comparator); - bool match(std::string const &source) const override; -}; - -struct RegexMatcher : MatcherBase { - RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity); - bool match(std::string const &matchee) const override; - std::string describe() const override; - -private: - std::string m_regex; - CaseSensitive::Choice m_caseSensitivity; -}; - -} // namespace StdString - -// The following functions create the actual matcher objects. -// This allows the types to be inferred - -StdString::EqualsMatcher Equals(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes); -StdString::ContainsMatcher Contains(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes); -StdString::EndsWithMatcher EndsWith(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes); -StdString::StartsWithMatcher StartsWith(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes); -StdString::RegexMatcher Matches(std::string const ®ex, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes); - -} // namespace Matchers -} // namespace Catch - -// end catch_matchers_string.h -// start catch_matchers_vector.h - -#include - -namespace Catch { -namespace Matchers { - -namespace Vector { -template -struct ContainsElementMatcher : MatcherBase> { - - ContainsElementMatcher(T const &comparator) - : m_comparator(comparator) - { - } - - bool match(std::vector const &v) const override - { - for (auto const &el : v) { - if (el == m_comparator) { - return true; - } - } - return false; - } - - std::string describe() const override - { - return "Contains: " + ::Catch::Detail::stringify(m_comparator); - } - - T const &m_comparator; -}; - -template -struct ContainsMatcher : MatcherBase> { - - ContainsMatcher(std::vector const &comparator) - : m_comparator(comparator) - { - } - - bool match(std::vector const &v) const override - { - // !TBD: see note in EqualsMatcher - if (m_comparator.size() > v.size()) - return false; - for (auto const &comparator : m_comparator) { - auto present = false; - for (const auto &el : v) { - if (el == comparator) { - present = true; - break; - } - } - if (!present) { - return false; - } - } - return true; - } - std::string describe() const override - { - return "Contains: " + ::Catch::Detail::stringify(m_comparator); - } - - std::vector const &m_comparator; -}; - -template -struct EqualsMatcher : MatcherBase> { - - EqualsMatcher(std::vector const &comparator) - : m_comparator(comparator) - { - } - - bool match(std::vector const &v) const override - { - // !TBD: This currently works if all elements can be compared using != - // - a more general approach would be via a compare template that - // defaults to using !=. but could be specialised for, e.g. - // std::vector etc - // - then just call that directly - if (m_comparator.size() != v.size()) - return false; - for (std::size_t i = 0; i < v.size(); ++i) - if (m_comparator[i] != v[i]) - return false; - return true; - } - std::string describe() const override - { - return "Equals: " + ::Catch::Detail::stringify(m_comparator); - } - std::vector const &m_comparator; -}; - -template -struct ApproxMatcher : MatcherBase> { - - ApproxMatcher(std::vector const &comparator) - : m_comparator(comparator) - { - } - - bool match(std::vector const &v) const override - { - if (m_comparator.size() != v.size()) - return false; - for (std::size_t i = 0; i < v.size(); ++i) - if (m_comparator[i] != approx(v[i])) - return false; - return true; - } - std::string describe() const override - { - return "is approx: " + ::Catch::Detail::stringify(m_comparator); - } - template ::value>::type> - ApproxMatcher &epsilon(T const &newEpsilon) - { - approx.epsilon(newEpsilon); - return *this; - } - template ::value>::type> - ApproxMatcher &margin(T const &newMargin) - { - approx.margin(newMargin); - return *this; - } - template ::value>::type> - ApproxMatcher &scale(T const &newScale) - { - approx.scale(newScale); - return *this; - } - - std::vector const &m_comparator; - mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom(); -}; - -template -struct UnorderedEqualsMatcher : MatcherBase> { - UnorderedEqualsMatcher(std::vector const &target) - : m_target(target) - { - } - bool match(std::vector const &vec) const override - { - if (m_target.size() != vec.size()) { - return false; - } - return std::is_permutation( - m_target.begin(), m_target.end(), vec.begin()); - } - - std::string describe() const override - { - return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); - } - -private: - std::vector const &m_target; -}; - -} // namespace Vector - -// The following functions create the actual matcher objects. -// This allows the types to be inferred - -template , - typename AllocMatch = AllocComp> -Vector::ContainsMatcher Contains( - std::vector const &comparator) -{ - return Vector::ContainsMatcher(comparator); -} - -template > -Vector::ContainsElementMatcher VectorContains(T const &comparator) -{ - return Vector::ContainsElementMatcher(comparator); -} - -template , - typename AllocMatch = AllocComp> -Vector::EqualsMatcher Equals( - std::vector const &comparator) -{ - return Vector::EqualsMatcher(comparator); -} - -template , - typename AllocMatch = AllocComp> -Vector::ApproxMatcher Approx( - std::vector const &comparator) -{ - return Vector::ApproxMatcher(comparator); -} - -template , - typename AllocMatch = AllocComp> -Vector::UnorderedEqualsMatcher UnorderedEquals( - std::vector const &target) -{ - return Vector::UnorderedEqualsMatcher(target); -} - -} // namespace Matchers -} // namespace Catch - -// end catch_matchers_vector.h -namespace Catch { - -template -class MatchExpr : public ITransientExpression { - ArgT const &m_arg; - MatcherT m_matcher; - StringRef m_matcherString; - -public: - MatchExpr(ArgT const &arg, MatcherT const &matcher, - StringRef const &matcherString) - : ITransientExpression{true, matcher.match(arg)} - , m_arg(arg) - , m_matcher(matcher) - , m_matcherString(matcherString) - { - } - - void streamReconstructedExpression(std::ostream &os) const override - { - auto matcherAsString = m_matcher.toString(); - os << Catch::Detail::stringify(m_arg) << ' '; - if (matcherAsString == Detail::unprintableString) - os << m_matcherString; - else - os << matcherAsString; - } -}; - -using StringMatcher = Matchers::Impl::MatcherBase; - -void handleExceptionMatchExpr(AssertionHandler &handler, - StringMatcher const &matcher, StringRef const &matcherString); - -template -auto makeMatchExpr(ArgT const &arg, MatcherT const &matcher, - StringRef const &matcherString) -> MatchExpr -{ - return MatchExpr(arg, matcher, matcherString); -} - -} // namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT(macroName, matcher, resultDisposition, arg) \ - do { \ - Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, \ - CATCH_INTERNAL_LINEINFO, \ - CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY( \ - matcher), \ - resultDisposition); \ - INTERNAL_CATCH_TRY \ - { \ - catchAssertionHandler.handleExpr( \ - Catch::makeMatchExpr(arg, matcher, #matcher##_catch_sr)); \ - } \ - INTERNAL_CATCH_CATCH(catchAssertionHandler) \ - INTERNAL_CATCH_REACT(catchAssertionHandler) \ - } while (false) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_MATCHES( \ - macroName, exceptionType, resultDisposition, matcher, ...) \ - do { \ - Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, \ - CATCH_INTERNAL_LINEINFO, \ - CATCH_INTERNAL_STRINGIFY( \ - __VA_ARGS__) "," \ - " " CATCH_INTERNAL_STRINGIFY( \ - exceptionType) "," \ - " " CATCH_INTERNAL_STRINGIFY( \ - matcher), \ - resultDisposition); \ - if (catchAssertionHandler.allowThrows()) \ - try { \ - static_cast(__VA_ARGS__); \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch (exceptionType const &ex) { \ - catchAssertionHandler.handleExpr( \ - Catch::makeMatchExpr(ex, matcher, #matcher##_catch_sr)); \ - } \ - catch (...) { \ - catchAssertionHandler.handleUnexpectedInflightException(); \ - } \ - else \ - catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT(catchAssertionHandler) \ - } while (false) - -// end catch_capture_matchers.h -#endif -// start catch_generators.hpp - -// start catch_interfaces_generatortracker.h - -#include - -namespace Catch { - -namespace Generators { -class GeneratorUntypedBase { -public: - GeneratorUntypedBase() = default; - virtual ~GeneratorUntypedBase(); - // Attempts to move the generator to the next element - // - // Returns true iff the move succeeded (and a valid element - // can be retrieved). - virtual bool next() = 0; -}; -using GeneratorBasePtr = std::unique_ptr; - -} // namespace Generators - -struct IGeneratorTracker { - virtual ~IGeneratorTracker(); - virtual auto hasGenerator() const -> bool = 0; - virtual auto getGenerator() const - -> Generators::GeneratorBasePtr const & = 0; - virtual void setGenerator(Generators::GeneratorBasePtr &&generator) = 0; -}; - -} // namespace Catch - -// end catch_interfaces_generatortracker.h -// start catch_enforce.h - -#include - -namespace Catch { -#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -template [[noreturn]] void throw_exception(Ex const &e) -{ - throw e; -} -#else // ^^ Exceptions are enabled // Exceptions are disabled vv -[[noreturn]] void throw_exception(std::exception const &e); -#endif - -[[noreturn]] void throw_logic_error(std::string const &msg); -[[noreturn]] void throw_domain_error(std::string const &msg); -[[noreturn]] void throw_runtime_error(std::string const &msg); - -} // namespace Catch; - -#define CATCH_MAKE_MSG(...) (Catch::ReusableStringStream() << __VA_ARGS__).str() - -#define CATCH_INTERNAL_ERROR(...) \ - Catch::throw_logic_error(CATCH_MAKE_MSG(CATCH_INTERNAL_LINEINFO \ - << ": Internal Catch2 error: " << __VA_ARGS__)) - -#define CATCH_ERROR(...) Catch::throw_domain_error(CATCH_MAKE_MSG(__VA_ARGS__)) - -#define CATCH_RUNTIME_ERROR(...) \ - Catch::throw_runtime_error(CATCH_MAKE_MSG(__VA_ARGS__)) - -#define CATCH_ENFORCE(condition, ...) \ - do { \ - if (!(condition)) \ - CATCH_ERROR(__VA_ARGS__); \ - } while (false) - -// end catch_enforce.h -#include -#include -#include - -#include -#include - -namespace Catch { - -class GeneratorException : public std::exception { - const char *const m_msg = ""; - -public: - GeneratorException(const char *msg) - : m_msg(msg) - { - } - - const char *what() const noexcept override final; -}; - -namespace Generators { - -// !TBD move this into its own location? -namespace pf { -template -std::unique_ptr make_unique(Args &&...args) -{ - return std::unique_ptr(new T(std::forward(args)...)); -} -} - -template struct IGenerator : GeneratorUntypedBase { - virtual ~IGenerator() = default; - - // Returns the current element of the generator - // - // \Precondition The generator is either freshly constructed, - // or the last call to `next()` returned true - virtual T const &get() const = 0; - using type = T; -}; - -template class SingleValueGenerator final : public IGenerator { - T m_value; - -public: - SingleValueGenerator(T &&value) - : m_value(std::move(value)) - { - } - - T const &get() const override { return m_value; } - bool next() override { return false; } -}; - -template class FixedValuesGenerator final : public IGenerator { - static_assert(!std::is_same::value, - "FixedValuesGenerator does not support bools because of " - "std::vector" - "specialization, use SingleValue Generator instead."); - std::vector m_values; - size_t m_idx = 0; - -public: - FixedValuesGenerator(std::initializer_list values) - : m_values(values) - { - } - - T const &get() const override { return m_values[m_idx]; } - bool next() override - { - ++m_idx; - return m_idx < m_values.size(); - } -}; - -template class GeneratorWrapper final { - std::unique_ptr> m_generator; - -public: - GeneratorWrapper(std::unique_ptr> generator) - : m_generator(std::move(generator)) - { - } - T const &get() const { return m_generator->get(); } - bool next() { return m_generator->next(); } -}; - -template GeneratorWrapper value(T &&value) -{ - return GeneratorWrapper( - pf::make_unique>(std::forward(value))); -} -template -GeneratorWrapper values(std::initializer_list values) -{ - return GeneratorWrapper( - pf::make_unique>(values)); -} - -template class Generators : public IGenerator { - std::vector> m_generators; - size_t m_current = 0; - - void populate(GeneratorWrapper &&generator) - { - m_generators.emplace_back(std::move(generator)); - } - void populate(T &&val) - { - m_generators.emplace_back(value(std::forward(val))); - } - template void populate(U &&val) - { - populate(T(std::forward(val))); - } - template - void populate(U &&valueOrGenerator, Gs &&...moreGenerators) - { - populate(std::forward(valueOrGenerator)); - populate(std::forward(moreGenerators)...); - } - -public: - template Generators(Gs &&...moreGenerators) - { - m_generators.reserve(sizeof...(Gs)); - populate(std::forward(moreGenerators)...); - } - - T const &get() const override { return m_generators[m_current].get(); } - - bool next() override - { - if (m_current >= m_generators.size()) { - return false; - } - const bool current_status = m_generators[m_current].next(); - if (!current_status) { - ++m_current; - } - return m_current < m_generators.size(); - } -}; - -template -GeneratorWrapper> table( - std::initializer_list::type...>> tuples) -{ - return values>(tuples); -} - -// Tag type to signal that a generator sequence should convert arguments to a -// specific type -template struct as { }; - -template -auto makeGenerators(GeneratorWrapper &&generator, Gs &&...moreGenerators) - -> Generators -{ - return Generators( - std::move(generator), std::forward(moreGenerators)...); -} -template -auto makeGenerators(GeneratorWrapper &&generator) -> Generators -{ - return Generators(std::move(generator)); -} -template -auto makeGenerators(T &&val, Gs &&...moreGenerators) -> Generators -{ - return makeGenerators( - value(std::forward(val)), std::forward(moreGenerators)...); -} -template -auto makeGenerators(as, U &&val, Gs &&...moreGenerators) -> Generators -{ - return makeGenerators( - value(T(std::forward(val))), std::forward(moreGenerators)...); -} - -auto acquireGeneratorTracker(StringRef generatorName, - SourceLineInfo const &lineInfo) -> IGeneratorTracker &; - -template -// Note: The type after -> is weird, because VS2015 cannot parse -// the expression used in the typedef inside, when it is in -// return type. Yeah. -auto generate(StringRef generatorName, SourceLineInfo const &lineInfo, - L const &generatorExpression) - -> decltype(std::declval().get()) -{ - using UnderlyingType = typename decltype(generatorExpression())::type; - - IGeneratorTracker &tracker = - acquireGeneratorTracker(generatorName, lineInfo); - if (!tracker.hasGenerator()) { - tracker.setGenerator( - pf::make_unique>(generatorExpression())); - } - - auto const &generator = static_cast const &>( - *tracker.getGenerator()); - return generator.get(); -} - -} // namespace Generators -} // namespace Catch - -#define GENERATE(...) \ - Catch::Generators::generate( \ - INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ - CATCH_INTERNAL_LINEINFO, [] { \ - using namespace Catch::Generators; \ - return makeGenerators(__VA_ARGS__); \ - }) // NOLINT(google-build-using-namespace) -#define GENERATE_COPY(...) \ - Catch::Generators::generate( \ - INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ - CATCH_INTERNAL_LINEINFO, [=] { \ - using namespace Catch::Generators; \ - return makeGenerators(__VA_ARGS__); \ - }) // NOLINT(google-build-using-namespace) -#define GENERATE_REF(...) \ - Catch::Generators::generate( \ - INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ - CATCH_INTERNAL_LINEINFO, [&] { \ - using namespace Catch::Generators; \ - return makeGenerators(__VA_ARGS__); \ - }) // NOLINT(google-build-using-namespace) - -// end catch_generators.hpp -// start catch_generators_generic.hpp - -namespace Catch { -namespace Generators { - -template class TakeGenerator : public IGenerator { - GeneratorWrapper m_generator; - size_t m_returned = 0; - size_t m_target; - -public: - TakeGenerator(size_t target, GeneratorWrapper &&generator) - : m_generator(std::move(generator)) - , m_target(target) - { - assert(target != 0 && "Empty generators are not allowed"); - } - T const &get() const override { return m_generator.get(); } - bool next() override - { - ++m_returned; - if (m_returned >= m_target) { - return false; - } - - const auto success = m_generator.next(); - // If the underlying generator does not contain enough values - // then we cut short as well - if (!success) { - m_returned = m_target; - } - return success; - } -}; - -template -GeneratorWrapper take(size_t target, GeneratorWrapper &&generator) -{ - return GeneratorWrapper( - pf::make_unique>(target, std::move(generator))); -} - -template -class FilterGenerator : public IGenerator { - GeneratorWrapper m_generator; - Predicate m_predicate; - -public: - template - FilterGenerator(P &&pred, GeneratorWrapper &&generator) - : m_generator(std::move(generator)) - , m_predicate(std::forward

")); + REQUIRE(IsField(src, "A", "ints", + "std::array")); + // TODO: add option to resolve using declared types + // REQUIRE(IsField(src, Public("bool (*)(int, int) comparator")); + REQUIRE(IsField( + src, "A", "comparator", "CMP")); - REQUIRE(model->name() == "t00008_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - // TODO: add option to resolve using declared types - // REQUIRE_THAT(puml, IsClassTemplate("A", "T, P, bool (*)(int, int), - // int N")); - REQUIRE_THAT(src, IsClassTemplate("A", "T,P=T,CMP=nullptr,int N=3")); - REQUIRE_THAT(src, IsClassTemplate("B", "T,C<>")); - - REQUIRE_THAT(src, (IsField("value", "T"))); - REQUIRE_THAT(src, (IsField("pointer", "T *"))); - REQUIRE_THAT(src, (IsField("reference", "T &"))); - REQUIRE_THAT(src, (IsField("values", "std::vector

"))); - REQUIRE_THAT(src, (IsField("ints", "std::array"))); - // TODO: add option to resolve using declared types - // REQUIRE_THAT(puml, IsField(Public("bool (*)(int, int) comparator"))); - REQUIRE_THAT(src, (IsField("comparator", "CMP"))); - - REQUIRE_THAT(src, !IsClass(_A("E::nested_template"))); - REQUIRE_THAT(src, IsClassTemplate("E::nested_template", "ET")); - REQUIRE_THAT(src, IsClassTemplate("E::nested_template", "char")); - REQUIRE_THAT(src, - IsInstantiation( - _A("E::nested_template"), _A("E::nested_template"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClassTemplate(j, "A")); - REQUIRE(IsClassTemplate(j, "E::nested_template")); - REQUIRE(IsClass(j, "E::nested_template")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - using mermaid::IsField; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B>"))); - - REQUIRE_THAT(src, (IsField("value", "T"))); - REQUIRE_THAT(src, (IsField("pointer", "T *"))); - REQUIRE_THAT(src, (IsField("reference", "T &"))); - REQUIRE_THAT(src, (IsField("values", "std::vector

"))); - REQUIRE_THAT(src, (IsField("ints", "std::array"))); - // TODO: add option to resolve using declared types - // REQUIRE_THAT(puml, IsField(Public("bool (*)(int, int) comparator"))); - REQUIRE_THAT(src, (IsField("comparator", "CMP"))); - - REQUIRE_THAT(src, !IsClass(_A("E::nested_template"))); - REQUIRE_THAT(src, IsClass(_A("E::nested_template"))); - REQUIRE_THAT(src, IsClass(_A("E::nested_template"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("E::nested_template"), _A("E::nested_template"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsClassTemplate(src, "E::nested_template")); + REQUIRE(IsClassTemplate(src, "E::nested_template")); + REQUIRE(IsInstantiation( + src, "E::nested_template", "E::nested_template")); + }, + [](const plantuml_t &src) { + REQUIRE(!IsClass(src, "E::nested_template")); + }); } \ No newline at end of file diff --git a/tests/t00009/test_case.h b/tests/t00009/test_case.h index 77885a25..9fdb667d 100644 --- a/tests/t00009/test_case.h +++ b/tests/t00009/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00009/test_case.cc + * tests/t00009/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,90 +16,31 @@ * limitations under the License. */ -TEST_CASE("t00009", "[test-case][class]") +TEST_CASE("t00009") { - auto [config, db] = load_config("t00009"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00009_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00009", "t00009_class"); - REQUIRE(diagram->name == "t00009_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClass(src, "B")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsField(src, "A", "value", "T")); + REQUIRE(IsField(src, "B", "aint", "A")); + REQUIRE(IsField(src, "B", "astring", "A *")); + REQUIRE(IsField( + src, "B", "avector", "A> &")); - REQUIRE(model->name() == "t00009_class"); + REQUIRE(IsInstantiation(src, "A", "A", "up")); + REQUIRE(IsInstantiation(src, "A", "A", "up")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClassTemplate("A", "T")); - REQUIRE_THAT(src, IsClass(_A("B"))); - - REQUIRE_THAT(src, (IsField("value", "T"))); - REQUIRE_THAT(src, (IsField("aint", "A"))); - REQUIRE_THAT(src, (IsField("astring", "A *"))); - REQUIRE_THAT( - src, (IsField("avector", "A> &"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"), "up")); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"), "up")); - - REQUIRE_THAT( - src, IsAggregation(_A("B"), _A("A"), "+aint", "", "", "up")); - REQUIRE_THAT(src, - IsAssociation( - _A("B"), _A("A"), "+astring", "", "", "up")); - REQUIRE_THAT(src, - IsAssociation(_A("B"), _A("A>"), - "+avector", "", "", "up")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClassTemplate(j, "A")); - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "A>")); - - REQUIRE(IsField(j, "A", "value", "T")); - REQUIRE(IsField(j, "B", "aint", "A")); - REQUIRE(IsField(j, "B", "astring", "A *")); - REQUIRE(IsField(j, "B", "avector", "A> &")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsField; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - - REQUIRE_THAT(src, (IsField("value", "T"))); - REQUIRE_THAT(src, (IsField("aint", "A"))); - REQUIRE_THAT(src, (IsField("astring", "A *"))); - REQUIRE_THAT( - src, (IsField("avector", "A> &"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - - REQUIRE_THAT(src, IsAggregation(_A("B"), _A("A"), "+aint")); - REQUIRE_THAT( - src, IsAssociation(_A("B"), _A("A"), "+astring")); - REQUIRE_THAT(src, - IsAssociation( - _A("B"), _A("A>"), "+avector")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE( + IsAggregation(src, "B", "A", "aint", "", "", "up")); + REQUIRE(IsAssociation( + src, "B", "A", "astring", "", "", "up")); + REQUIRE(IsAssociation( + src, "B", "A>", "avector", "", "", "up")); + }); } \ No newline at end of file diff --git a/tests/t00010/test_case.h b/tests/t00010/test_case.h index 83dca628..6dfb726e 100644 --- a/tests/t00010/test_case.h +++ b/tests/t00010/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00010/test_case.cc + * tests/t00010/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,75 +16,25 @@ * limitations under the License. */ -TEST_CASE("t00010", "[test-case][class]") +TEST_CASE("t00010") { - auto [config, db] = load_config("t00010"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00010_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00010", "t00010_class"); - REQUIRE(diagram->name == "t00010_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "B")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsField(src, "B", "astring", "A")); + REQUIRE(IsField(src, "C", "aintstring", "B")); - REQUIRE(model->name() == "t00010_class"); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "B", "B")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClassTemplate("A", "T,P")); - REQUIRE_THAT(src, IsClassTemplate("B", "T")); - - REQUIRE_THAT(src, (IsField("astring", "A"))); - REQUIRE_THAT(src, (IsField("aintstring", "B"))); - - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("B"), _A("B"))); - - REQUIRE_THAT( - src, IsAggregation(_A("B"), _A("A"), "+astring")); - REQUIRE_THAT(src, IsAggregation(_A("C"), _A("B"), "+aintstring")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClassTemplate(j, "A")); - REQUIRE(IsClassTemplate(j, "B")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - - REQUIRE(IsField(j, "C", "aintstring", "B")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsField; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - - REQUIRE_THAT(src, (IsField("astring", "A"))); - REQUIRE_THAT(src, (IsField("aintstring", "B"))); - - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("B"), _A("B"))); - - REQUIRE_THAT( - src, IsAggregation(_A("B"), _A("A"), "+astring")); - REQUIRE_THAT(src, IsAggregation(_A("C"), _A("B"), "+aintstring")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE( + IsAggregation(src, "B", "A", "astring")); + REQUIRE(IsAggregation(src, "C", "B", "aintstring")); + }); } \ No newline at end of file diff --git a/tests/t00011/test_case.h b/tests/t00011/test_case.h index a5c7d53a..cd05c673 100644 --- a/tests/t00011/test_case.h +++ b/tests/t00011/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00011/test_case.cc + * tests/t00011/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,60 +16,20 @@ * limitations under the License. */ -TEST_CASE("t00011", "[test-case][class]") +TEST_CASE("t00011") { - auto [config, db] = load_config("t00011"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00011_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00011", "t00011_class"); - REQUIRE(diagram->name == "t00011_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(!IsClass(src, "external::C")); + REQUIRE(IsClassTemplate(src, "D")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00011_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("external::C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - - REQUIRE_THAT(src, IsAssociation(_A("B"), _A("A"))); - REQUIRE_THAT(src, IsFriend(_A("A"), _A("B"))); - // REQUIRE_THAT(puml, IsFriend(_A("A"), _A("D"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClassTemplate(j, "D")); - REQUIRE(IsFriend(j, "A", "B")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsFriend; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("external::C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - - REQUIRE_THAT(src, IsAssociation(_A("B"), _A("A"))); - REQUIRE_THAT(src, IsFriend(_A("A"), _A("B"))); - // REQUIRE_THAT(src, IsFriend(_A("A"), _A("D"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAssociation(src, "B", "A")); + REQUIRE(IsFriend(src, "A", "B")); + }); } \ No newline at end of file diff --git a/tests/t00012/test_case.h b/tests/t00012/test_case.h index 8b1a9d6a..02a6af31 100644 --- a/tests/t00012/test_case.h +++ b/tests/t00012/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00012/test_case.cc + * tests/t00012/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,70 +16,22 @@ * limitations under the License. */ -TEST_CASE("t00012", "[test-case][class]") +TEST_CASE("t00012") { - auto [config, db] = load_config("t00012"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00012_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00012", "t00012_class"); - REQUIRE(diagram->name == "t00012_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "B")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00012_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClassTemplate("A", "T,Ts...")); - REQUIRE_THAT(src, IsClassTemplate("B", "int... Is")); - - REQUIRE_THAT(src, IsInstantiation(_A("B"), _A("B<3,2,1>"))); - REQUIRE_THAT( - src, IsInstantiation(_A("B"), _A("B<1,1,1,1>"))); - REQUIRE_THAT(src, - IsInstantiation(_A("C"), - _A("C>>>,3,3," - "3>"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClassTemplate(j, "A")); - REQUIRE(IsClassTemplate(j, "B")); - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, - "C>>>" - ",3,3,3>")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - - REQUIRE_THAT(src, IsInstantiation(_A("B"), _A("B<3,2,1>"))); - REQUIRE_THAT( - src, IsInstantiation(_A("B"), _A("B<1,1,1,1>"))); - REQUIRE_THAT(src, - IsInstantiation(_A("C"), - _A("C>>>,3,3," - "3>"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsInstantiation(src, "B", "B<3,2,1>")); + REQUIRE(IsInstantiation(src, "B", "B<1,1,1,1>")); + REQUIRE(IsInstantiation(src, "C", + "C>>>,3,3," + "3>")); + }); } \ No newline at end of file diff --git a/tests/t00013/test_case.h b/tests/t00013/test_case.h index f12a999b..7f96873f 100644 --- a/tests/t00013/test_case.h +++ b/tests/t00013/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00013/test_case.cc + * tests/t00013/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,107 +16,36 @@ * limitations under the License. */ -TEST_CASE("t00013", "[test-case][class]") +TEST_CASE("t00013") { - auto [config, db] = load_config("t00013"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00013_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00013", "t00013_class"); - REQUIRE(diagram->name == "t00013_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClassTemplate(src, "E")); + REQUIRE(IsClassTemplate(src, "G")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00013_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClassTemplate("E", "T")); - REQUIRE_THAT(src, IsClassTemplate("G", "T,Args...")); - - REQUIRE_THAT(src, !IsDependency(_A("R"), _A("R"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("A"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("B"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("C"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("D"))); - REQUIRE_THAT(src, IsDependency(_A("D"), _A("R"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("E"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("E"))); - REQUIRE_THAT(src, IsInstantiation(_A("E"), _A("E"))); - REQUIRE_THAT(src, IsInstantiation(_A("E"), _A("E"))); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("E"), "-estring")); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("ABCD::F"))); - REQUIRE_THAT( - src, IsInstantiation(_A("ABCD::F"), _A("ABCD::F"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("ABCD::F"))); - - REQUIRE_THAT(src, - IsInstantiation( - _A("G"), _A("G"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsClass(j, "D")); - REQUIRE(IsInstantiation(j, "E", "E")); - REQUIRE(IsDependency(j, "R", "A")); - REQUIRE(IsDependency(j, "R", "B")); - REQUIRE(IsDependency(j, "R", "C")); - REQUIRE(IsDependency(j, "R", "D")); - REQUIRE(IsDependency(j, "D", "R")); - REQUIRE(IsDependency(j, "R", "E")); - REQUIRE(IsInstantiation(j, "G", "G")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - - REQUIRE_THAT(src, !IsDependency(_A("R"), _A("R"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("A"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("B"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("C"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("D"))); - REQUIRE_THAT(src, IsDependency(_A("D"), _A("R"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("E"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("E"))); - REQUIRE_THAT(src, IsInstantiation(_A("E"), _A("E"))); - REQUIRE_THAT(src, IsInstantiation(_A("E"), _A("E"))); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("E"), "-estring")); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("ABCD::F"))); - REQUIRE_THAT( - src, IsInstantiation(_A("ABCD::F"), _A("ABCD::F"))); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("ABCD::F"))); - - REQUIRE_THAT(src, - IsInstantiation( - _A("G"), _A("G"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!IsDependency(src, "R", "R")); + REQUIRE(IsDependency(src, "R", "A")); + REQUIRE(IsDependency(src, "R", "B")); + REQUIRE(IsDependency(src, "R", "C")); + REQUIRE(IsDependency(src, "R", "D")); + REQUIRE(IsDependency(src, "D", "R")); + REQUIRE(IsDependency(src, "R", "E")); + REQUIRE(IsDependency(src, "R", "E")); + REQUIRE(IsInstantiation(src, "E", "E")); + REQUIRE(IsInstantiation(src, "E", "E")); + REQUIRE(IsAggregation(src, "R", "E", "estring")); + REQUIRE(IsDependency(src, "R", "ABCD::F")); + REQUIRE(IsInstantiation(src, "ABCD::F", "ABCD::F")); + REQUIRE(IsDependency(src, "R", "ABCD::F")); + REQUIRE( + IsInstantiation(src, "G", "G")); + }); } \ No newline at end of file diff --git a/tests/t00014/test_case.h b/tests/t00014/test_case.h index 0368ba2d..0829306f 100644 --- a/tests/t00014/test_case.h +++ b/tests/t00014/test_case.h @@ -16,267 +16,107 @@ * limitations under the License. */ -TEST_CASE("t00014", "[test-case][class]") +TEST_CASE("t00014") { - auto [config, db] = load_config("t00014"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00014_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00014", "t00014_class"); - REQUIRE(diagram->name == "t00014_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!src.contains("type-parameter-")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00014_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, !Contains("type-parameter-")); - - REQUIRE_THAT(src, IsClassTemplate("A", "T,P")); - REQUIRE_THAT(src, IsClassTemplate("A", "T,std::string")); - REQUIRE_THAT( - src, IsClassTemplate("A", "T,std::unique_ptr")); - REQUIRE_THAT(src, IsClassTemplate("A", "double,T")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A>")); + REQUIRE(IsClassTemplate(src, "A")); // TODO: Figure out how to handle the same templates with different // template // parameter names - // REQUIRE_THAT(puml, !IsClassTemplate("A", "long,U")); - REQUIRE_THAT(src, IsClassTemplate("A", "long,T")); - REQUIRE_THAT(src, IsClassTemplate("A", "long,bool")); - REQUIRE_THAT(src, IsClassTemplate("A", "double,bool")); - REQUIRE_THAT(src, IsClassTemplate("A", "long,float")); - REQUIRE_THAT(src, IsClassTemplate("A", "double,float")); - REQUIRE_THAT(src, IsClassTemplate("A", "bool,std::string")); - REQUIRE_THAT(src, IsClassTemplate("A", "std::string,std::string")); - REQUIRE_THAT(src, IsClassTemplate("A", "char,std::string")); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClassTemplate("R", "T")); + // REQUIRE(puml, !IsClassTemplate("A", "long,U")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClassTemplate(src, "R")); - REQUIRE_THAT(src, IsField("bapair", "PairPairBA")); - REQUIRE_THAT(src, IsField("abool", "APtr")); - REQUIRE_THAT(src, IsField("aboolfloat", "AAPtr")); - REQUIRE_THAT(src, IsField("afloat", "ASharedPtr")); - REQUIRE_THAT( - src, IsField("boolstring", "A")); - REQUIRE_THAT(src, IsField("floatstring", "AStringPtr")); - REQUIRE_THAT(src, IsField("atfloat", "AAPtr")); + REQUIRE(IsField(src, "R", "bapair", "PairPairBA")); + REQUIRE(IsField(src, "R", "abool", "APtr")); + REQUIRE( + IsField(src, "R", "aboolfloat", "AAPtr")); + REQUIRE(IsField(src, "R", "afloat", "ASharedPtr")); + REQUIRE( + IsField(src, "R", "boolstring", "A")); + REQUIRE( + IsField(src, "R", "floatstring", "AStringPtr")); + REQUIRE(IsField(src, "R", "atfloat", "AAPtr")); - REQUIRE_THAT(src, IsField("intstring", "AIntString")); - REQUIRE_THAT(src, IsField("stringstring", "AStringString")); - REQUIRE_THAT(src, IsField("bstringstring", "BStringString")); + REQUIRE(IsField(src, "R", "intstring", "AIntString")); + REQUIRE(IsField(src, "R", "stringstring", "AStringString")); + REQUIRE( + IsField(src, "R", "bstringstring", "BStringString")); - REQUIRE_THAT(src, IsField("bs", "BVector")); + REQUIRE(IsField(src, "R", "bs", "BVector")); - REQUIRE_THAT(src, IsField("cb", "SimpleCallback")); + REQUIRE( + IsField(src, "R", "cb", "SimpleCallback")); #if LLVM_VERSION_MAJOR >= 16 - REQUIRE_THAT( - src, IsField("gcb", "GenericCallback")); + REQUIRE(IsField( + src, "R", "gcb", "GenericCallback")); #else - REQUIRE_THAT( - src, IsField("gcb", "GenericCallback")); + REQUIRE( + IsField(src, "R", "gcb", "GenericCallback")); #endif - REQUIRE_THAT(src, IsField("vcb", "VoidCallback")); + REQUIRE(IsField(src, "R", "vcb", "VoidCallback")); - REQUIRE_THAT( - src, !IsClassTemplate("std::std::function", "void(T...,int),int)")); + REQUIRE( + !IsClassTemplate(src, "std::std::function")); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - // REQUIRE_THAT(puml, !IsInstantiation(_A("A"), + REQUIRE(IsInstantiation(src, "A", "A")); + // REQUIRE(puml, !IsInstantiation(_A("A"), // _A("A"))); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, - IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, - IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("A"), _A("A"))); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE( + IsInstantiation(src, "A", "A")); + REQUIRE( + IsInstantiation(src, "A", "A")); + REQUIRE( + IsInstantiation(src, "A", "A")); - REQUIRE_THAT(src, - IsInstantiation(_A("A>"), - _A("A>"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("A"), _A("A>"))); + REQUIRE(IsInstantiation(src, "A>", + "A>")); + REQUIRE(IsInstantiation( + src, "A", "A>")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("B"), "+vps")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("B"), "-bapair")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("A"), "-aboolfloat")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("A"), "-bapair")); - REQUIRE_THAT(src, - IsAggregation(_A("R"), _A("A"), "-aboolfloat")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("A"), "-atfloat")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("A"), "-atfloat")); - REQUIRE_THAT( - src, IsAssociation(_A("R"), _A("A"), "-afloat")); - REQUIRE_THAT(src, - IsAggregation( - _A("R"), _A("A"), "-boolstring")); - REQUIRE_THAT(src, - IsAggregation(_A("R"), - _A("A>"), "-floatstring")); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("A"))); - REQUIRE_THAT( - src, IsDependency(_A("R"), _A("A"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A>")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "A")); - REQUIRE(json::IsClass(j, "B")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsField; - - REQUIRE_THAT(src, !Contains("type-parameter-")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A>"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - // TODO: Figure out how to handle the same templates with different - // template - // parameter names - // REQUIRE_THAT(puml, !IsClass("A", "long,U")); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsField("bapair", "PairPairBA")); - REQUIRE_THAT(src, IsField("abool", "APtr")); - REQUIRE_THAT(src, IsField("aboolfloat", "AAPtr")); - REQUIRE_THAT(src, IsField("afloat", "ASharedPtr")); - REQUIRE_THAT( - src, IsField("boolstring", "A")); - REQUIRE_THAT(src, IsField("floatstring", "AStringPtr")); - REQUIRE_THAT(src, IsField("atfloat", "AAPtr")); - - REQUIRE_THAT(src, IsField("intstring", "AIntString")); - REQUIRE_THAT(src, IsField("stringstring", "AStringString")); - REQUIRE_THAT(src, IsField("bstringstring", "BStringString")); - - REQUIRE_THAT(src, IsField("bs", "BVector")); - - REQUIRE_THAT(src, IsField("cb", "SimpleCallback")); -#if LLVM_VERSION_MAJOR >= 16 - REQUIRE_THAT( - src, IsField("gcb", "GenericCallback")); -#else - REQUIRE_THAT( - src, IsField("gcb", "GenericCallback")); -#endif - REQUIRE_THAT(src, IsField("vcb", "VoidCallback")); - - REQUIRE_THAT( - src, !IsClassTemplate("std::std::function", "void(T...,int),int)")); - - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - // REQUIRE_THAT(puml, !IsInstantiation(_A("A"), - // _A("A"))); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, - IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, - IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("A"), _A("A"))); - - REQUIRE_THAT(src, - IsInstantiation(_A("A>"), - _A("A>"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("A"), _A("A>"))); - - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("B"), "+vps")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("B"), "-bapair")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("A"), "-aboolfloat")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("A"), "-bapair")); - REQUIRE_THAT(src, - IsAggregation(_A("R"), _A("A"), "-aboolfloat")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("A"), "-atfloat")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("A"), "-atfloat")); - REQUIRE_THAT( - src, IsAssociation(_A("R"), _A("A"), "-afloat")); - REQUIRE_THAT(src, - IsAggregation( - _A("R"), _A("A"), "-boolstring")); - REQUIRE_THAT(src, - IsAggregation(_A("R"), - _A("A>"), "-floatstring")); -#if !defined(__APPLE__) - // TODO(#176) - REQUIRE_THAT(src, IsDependency(_A("R"), _A("A"))); - REQUIRE_THAT( - src, IsDependency(_A("R"), _A("A"))); -#endif - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAggregation(src, "R", "B", "vps")); + REQUIRE(IsAggregation(src, "R", "B", "bapair")); + REQUIRE( + IsAggregation(src, "R", "A", "aboolfloat")); + REQUIRE(IsAggregation(src, "R", "A", "bapair")); + REQUIRE(IsAggregation( + src, "R", "A", "aboolfloat")); + REQUIRE(IsAggregation(src, "R", "A", "atfloat")); + REQUIRE( + IsAggregation(src, "R", "A", "atfloat")); + REQUIRE( + IsAssociation(src, "R", "A", "afloat")); + REQUIRE(IsAggregation( + src, "R", "A", "boolstring")); + REQUIRE(IsAggregation(src, "R", + "A>", "floatstring")); + REQUIRE(IsDependency(src, "R", "A")); + REQUIRE(IsDependency(src, "R", "A")); + }); } \ No newline at end of file diff --git a/tests/t00015/test_case.h b/tests/t00015/test_case.h index 42752d54..34f32410 100644 --- a/tests/t00015/test_case.h +++ b/tests/t00015/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00015/test_case.cc + * tests/t00015/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,56 +16,18 @@ * limitations under the License. */ -TEST_CASE("t00015", "[test-case][class]") +TEST_CASE("t00015") { - auto [config, db] = load_config("t00015"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00015_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00015", "t00015_class"); - REQUIRE(diagram->name == "t00015_class"); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00015_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClass(_A("ns1::A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2_v0_9_0::A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::Anon"))); - REQUIRE_THAT(src, IsClass(_A("ns3::ns1::ns2::Anon"))); - REQUIRE_THAT(src, IsClass(_A("ns3::B"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "ns1::A")); - REQUIRE(IsClass(j, "ns1::ns2_v0_9_0::A")); - REQUIRE(IsClass(j, "ns1::Anon")); - REQUIRE(IsClass(j, "ns3::ns1::ns2::Anon")); - REQUIRE(IsClass(j, "ns3::B")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("ns1::A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2_v0_9_0::A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::Anon"))); - REQUIRE_THAT(src, IsClass(_A("ns3::ns1::ns2::Anon"))); - REQUIRE_THAT(src, IsClass(_A("ns3::B"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "ns1::A")); + REQUIRE(IsClass(src, "ns1::ns2_v0_9_0::A")); + REQUIRE(IsClass(src, "ns1::Anon")); + REQUIRE(IsClass(src, "ns3::ns1::ns2::Anon")); + REQUIRE(IsClass(src, "ns3::B")); + }); } \ No newline at end of file diff --git a/tests/t00016/test_case.h b/tests/t00016/test_case.h index 5efdbe20..a4e0dfbc 100644 --- a/tests/t00016/test_case.h +++ b/tests/t00016/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00016/test_case.cc + * tests/t00016/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,81 +16,27 @@ * limitations under the License. */ -TEST_CASE("t00016", "[test-case][class]") +TEST_CASE("t00016") { - auto [config, db] = load_config("t00016"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00016_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00016", "t00016_class"); - REQUIRE(diagram->name == "t00016_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClassTemplate(src, "is_numeric")); + REQUIRE(IsClassTemplate(src, "is_numeric")); + REQUIRE(IsClassTemplate(src, "is_numeric")); + REQUIRE(IsClassTemplate(src, "is_numeric")); + REQUIRE(IsClassTemplate(src, "is_numeric")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00016_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClassTemplate("is_numeric", "typename")); - REQUIRE_THAT(src, IsClassTemplate("is_numeric", "int")); - REQUIRE_THAT(src, IsClassTemplate("is_numeric", "bool")); - REQUIRE_THAT(src, IsClassTemplate("is_numeric", "char")); - REQUIRE_THAT(src, IsClassTemplate("is_numeric", "float")); - - REQUIRE_THAT(src, - IsInstantiation( - _A("is_numeric"), _A("is_numeric"), "up")); - REQUIRE_THAT(src, - IsInstantiation( - _A("is_numeric"), _A("is_numeric"), "up")); - REQUIRE_THAT(src, - IsInstantiation( - _A("is_numeric"), _A("is_numeric"), "up")); - REQUIRE_THAT(src, - IsInstantiation( - _A("is_numeric"), _A("is_numeric"), "up")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClassTemplate(j, "is_numeric")); - REQUIRE(IsClass(j, "is_numeric")); - REQUIRE(IsClass(j, "is_numeric")); - REQUIRE(IsClass(j, "is_numeric")); - REQUIRE(IsClass(j, "is_numeric")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("is_numeric"))); - REQUIRE_THAT(src, IsClass(_A("is_numeric"))); - REQUIRE_THAT(src, IsClass(_A("is_numeric"))); - REQUIRE_THAT(src, IsClass(_A("is_numeric"))); - REQUIRE_THAT(src, IsClass(_A("is_numeric"))); - - REQUIRE_THAT(src, - IsInstantiation(_A("is_numeric"), _A("is_numeric"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("is_numeric"), _A("is_numeric"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("is_numeric"), _A("is_numeric"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("is_numeric"), _A("is_numeric"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsInstantiation( + src, "is_numeric", "is_numeric", "up")); + REQUIRE(IsInstantiation( + src, "is_numeric", "is_numeric", "up")); + REQUIRE(IsInstantiation( + src, "is_numeric", "is_numeric", "up")); + REQUIRE(IsInstantiation( + src, "is_numeric", "is_numeric", "up")); + }); } \ No newline at end of file diff --git a/tests/t00017/test_case.h b/tests/t00017/test_case.h index 865764ba..bf61fb62 100644 --- a/tests/t00017/test_case.h +++ b/tests/t00017/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00017/test_case.cc + * tests/t00017/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,119 +16,54 @@ * limitations under the License. */ -TEST_CASE("t00017", "[test-case][class]") +TEST_CASE("t00017") { - auto [config, db] = load_config("t00017"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00017_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00017", "t00017_class"); - REQUIRE(diagram->name == "t00017_class"); + CHECK_CLASS_DIAGRAM( + config, diagram, *model, + [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClass(src, "E")); + REQUIRE(IsClass(src, "F")); + REQUIRE(IsClass(src, "G")); + REQUIRE(IsClass(src, "H")); + REQUIRE(IsClass(src, "I")); + REQUIRE(IsClass(src, "J")); + REQUIRE(IsClass(src, "K")); + REQUIRE(IsClass(src, "R")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsField(src, "R", "some_int", "int")); + REQUIRE((IsField(src, "R", "some_int_pointer", "int *"))); + REQUIRE((IsField( + src, "R", "some_int_pointer_pointer", "int **"))); - REQUIRE(model->name() == "t00017_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - REQUIRE_THAT(src, IsClass(_A("H"))); - REQUIRE_THAT(src, IsClass(_A("I"))); - REQUIRE_THAT(src, IsClass(_A("J"))); - REQUIRE_THAT(src, IsClass(_A("K"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, (IsField("some_int", "int"))); - REQUIRE_THAT(src, (IsField("some_int_pointer", "int *"))); - REQUIRE_THAT( - src, (IsField("some_int_pointer_pointer", "int **"))); - - // Relationship members should not be rendered as part of this testcase - REQUIRE_THAT(src, !(IsField("a", _A("A")))); - REQUIRE_THAT(src, !(IsField("b", _A("B")))); - - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("A"), "-a")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("B"), "-b")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("C"), "-c")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("D"), "-d")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("E"), "-e")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("F"), "-f")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("G"), "-g")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("H"), "-h")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("I"), "-i")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("J"), "-j")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("K"), "-k")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsClass(j, "D")); - REQUIRE(IsClass(j, "E")); - REQUIRE(IsClass(j, "F")); - REQUIRE(IsClass(j, "G")); - REQUIRE(IsClass(j, "H")); - REQUIRE(IsClass(j, "I")); - REQUIRE(IsClass(j, "J")); - REQUIRE(IsClass(j, "K")); - REQUIRE(IsClass(j, "R")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsField; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - REQUIRE_THAT(src, IsClass(_A("H"))); - REQUIRE_THAT(src, IsClass(_A("I"))); - REQUIRE_THAT(src, IsClass(_A("J"))); - REQUIRE_THAT(src, IsClass(_A("K"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, (IsField("some_int", "int"))); - REQUIRE_THAT(src, (IsField("some_int_pointer", "int *"))); - REQUIRE_THAT( - src, (IsField("some_int_pointer_pointer", "int **"))); - - // Relationship members should not be rendered as part of this testcase - REQUIRE_THAT(src, !(IsField("a", _A("A")))); - REQUIRE_THAT(src, !(IsField("b", _A("B")))); - - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("A"), "-a")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("B"), "-b")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("C"), "-c")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("D"), "-d")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("E"), "-e")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("F"), "-f")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("G"), "-g")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("H"), "-h")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("I"), "-i")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("J"), "-j")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("K"), "-k")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAggregation(src, "R", "A", "a")); + REQUIRE(IsAssociation(src, "R", "B", "b")); + REQUIRE(IsAssociation(src, "R", "C", "c")); + REQUIRE(IsAssociation(src, "R", "D", "d")); + REQUIRE(IsAssociation(src, "R", "E", "e")); + REQUIRE(IsAggregation(src, "R", "F", "f")); + REQUIRE(IsAssociation(src, "R", "G", "g")); + REQUIRE(IsAssociation(src, "R", "H", "h")); + REQUIRE(IsAssociation(src, "R", "I", "i")); + REQUIRE(IsAssociation(src, "R", "J", "j")); + REQUIRE(IsAssociation(src, "R", "K", "k")); + }, + [](const plantuml_t &src) { + // Relationship members should not be rendered as part of this + // testcase + REQUIRE(!IsField(src, "R", "a", "A")); + REQUIRE(!IsField(src, "R", "b", "B")); + }, + [](const mermaid_t &src) { + REQUIRE(!IsField(src, "R", "a", "A")); + REQUIRE(!IsField(src, "R", "b", "B")); + }); } \ No newline at end of file diff --git a/tests/t00018/test_case.h b/tests/t00018/test_case.h index 8ca24e0b..5ab46a7e 100644 --- a/tests/t00018/test_case.h +++ b/tests/t00018/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00018/test_case.cc + * tests/t00018/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,57 +16,20 @@ * limitations under the License. */ -TEST_CASE("t00018", "[test-case][class]") +TEST_CASE("t00018") { - auto [config, db] = load_config("t00018"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00018_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00018", "t00018_class"); - REQUIRE(diagram->name == "t00018_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "widget")); + REQUIRE(IsClass(src, "impl::widget")); + REQUIRE(IsDependency(src, "impl::widget", "widget")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00018_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClass(_A("widget"))); - REQUIRE_THAT(src, IsClass(_A("impl::widget"))); - - REQUIRE_THAT( - src, IsAggregation(_A("widget"), _A("impl::widget"), "-pImpl")); - REQUIRE_THAT(src, IsDependency(_A("impl::widget"), _A("widget"))); - REQUIRE_THAT(src, !IsDependency(_A("widget"), _A("widget"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "widget")); - REQUIRE(IsClass(j, "impl::widget")); - REQUIRE(IsDependency(j, "impl::widget", "widget")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("widget"))); - REQUIRE_THAT(src, IsClass(_A("impl::widget"))); - - REQUIRE_THAT( - src, IsAggregation(_A("widget"), _A("impl::widget"), "-pImpl")); - REQUIRE_THAT(src, IsDependency(_A("impl::widget"), _A("widget"))); - REQUIRE_THAT(src, !IsDependency(_A("widget"), _A("widget"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAggregation(src, "widget", "impl::widget", "pImpl")); + REQUIRE(IsDependency(src, "impl::widget", "widget")); + REQUIRE(!IsDependency(src, "widget", "widget")); + }); } \ No newline at end of file diff --git a/tests/t00019/test_case.h b/tests/t00019/test_case.h index d7bdb746..ceab5e62 100644 --- a/tests/t00019/test_case.h +++ b/tests/t00019/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00019/test_case.cc + * tests/t00019/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,113 +16,40 @@ * limitations under the License. */ -TEST_CASE("t00019", "[test-case][class]") +TEST_CASE("t00019") { - auto [config, db] = load_config("t00019"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00019_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00019", "t00019_class"); - REQUIRE(diagram->name == "t00019_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "Base")); + REQUIRE(IsClassTemplate(src, "Layer1")); + REQUIRE(IsClassTemplate(src, "Layer2")); + REQUIRE(IsClassTemplate(src, "Layer3")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsBaseClass(src, "Base", "Layer3")); + REQUIRE(!IsDependency(src, "Base", "Layer3")); - REQUIRE(model->name() == "t00019_class"); + REQUIRE(IsBaseClass(src, "Layer3", "Layer2>")); + REQUIRE(!IsDependency(src, "Layer3", "Layer2>")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsBaseClass( + src, "Layer2>", "Layer1>>")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClass(_A("Base"))); - REQUIRE_THAT(src, IsClassTemplate("Layer1", "LowerLayer")); - REQUIRE_THAT(src, IsClassTemplate("Layer2", "LowerLayer")); - REQUIRE_THAT(src, IsClassTemplate("Layer3", "LowerLayer")); + REQUIRE(!IsDependency( + src, "Layer2>", "Layer1>>")); - REQUIRE_THAT(src, IsBaseClass(_A("Base"), _A("Layer3"))); - REQUIRE_THAT(src, !IsDependency(_A("Base"), _A("Layer3"))); + REQUIRE(IsAggregation( + src, "A", "Layer1>>", "layers")); + REQUIRE(!IsDependency(src, "A", "Layer1>>")); - REQUIRE_THAT( - src, IsBaseClass(_A("Layer3"), _A("Layer2>"))); - REQUIRE_THAT( - src, !IsDependency(_A("Layer3"), _A("Layer2>"))); + REQUIRE( + !IsAggregation(src, "A", "Layer2>", "layers")); - REQUIRE_THAT(src, - IsBaseClass(_A("Layer2>"), - _A("Layer1>>"))); + REQUIRE(!IsAggregation(src, "A", "Layer3", "layers")); - REQUIRE_THAT(src, - !IsDependency(_A("Layer2>"), - _A("Layer1>>"))); - - REQUIRE_THAT(src, - IsAggregation( - _A("A"), _A("Layer1>>"), "+layers")); - REQUIRE_THAT( - src, !IsDependency(_A("A"), _A("Layer1>>"))); - - REQUIRE_THAT(src, - !IsAggregation(_A("A"), _A("Layer2>"), "+layers")); - - REQUIRE_THAT( - src, !IsAggregation(_A("A"), _A("Layer3"), "+layers")); - - REQUIRE_THAT(src, !IsAggregation(_A("A"), _A("Base"), "+layers")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "Base")); - REQUIRE(IsClassTemplate(j, "Layer1")); - REQUIRE(IsClassTemplate(j, "Layer2")); - REQUIRE(IsClassTemplate(j, "Layer3")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("Base"))); - REQUIRE_THAT(src, IsClass(_A("Layer1"))); - REQUIRE_THAT(src, IsClass(_A("Layer2"))); - REQUIRE_THAT(src, IsClass(_A("Layer3"))); - - REQUIRE_THAT(src, IsBaseClass(_A("Base"), _A("Layer3"))); - REQUIRE_THAT(src, !IsDependency(_A("Base"), _A("Layer3"))); - - REQUIRE_THAT( - src, IsBaseClass(_A("Layer3"), _A("Layer2>"))); - REQUIRE_THAT( - src, !IsDependency(_A("Layer3"), _A("Layer2>"))); - - REQUIRE_THAT(src, - IsBaseClass(_A("Layer2>"), - _A("Layer1>>"))); - - REQUIRE_THAT(src, - !IsDependency(_A("Layer2>"), - _A("Layer1>>"))); - - REQUIRE_THAT(src, - IsAggregation( - _A("A"), _A("Layer1>>"), "+layers")); - REQUIRE_THAT( - src, !IsDependency(_A("A"), _A("Layer1>>"))); - - REQUIRE_THAT(src, - !IsAggregation(_A("A"), _A("Layer2>"), "+layers")); - - REQUIRE_THAT( - src, !IsAggregation(_A("A"), _A("Layer3"), "+layers")); - - REQUIRE_THAT(src, !IsAggregation(_A("A"), _A("Base"), "+layers")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!IsAggregation(src, "A", "Base", "layers")); + }); } \ No newline at end of file diff --git a/tests/t00020/test_case.h b/tests/t00020/test_case.h index d959b04c..bef7d8c8 100644 --- a/tests/t00020/test_case.h +++ b/tests/t00020/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00020/test_case.cc + * tests/t00020/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,65 +16,22 @@ * limitations under the License. */ -TEST_CASE("t00020", "[test-case][class]") +TEST_CASE("t00020") { - auto [config, db] = load_config("t00020"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00020_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00020", "t00020_class"); - REQUIRE(diagram->name == "t00020_class"); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00020_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsAbstractClass(_A("ProductA"))); - REQUIRE_THAT(src, IsAbstractClass(_A("ProductB"))); - REQUIRE_THAT(src, IsClass(_A("ProductA1"))); - REQUIRE_THAT(src, IsClass(_A("ProductA2"))); - REQUIRE_THAT(src, IsClass(_A("ProductB1"))); - REQUIRE_THAT(src, IsClass(_A("ProductB2"))); - REQUIRE_THAT(src, IsAbstractClass(_A("AbstractFactory"))); - REQUIRE_THAT(src, IsClass(_A("Factory1"))); - REQUIRE_THAT(src, IsClass(_A("Factory2"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "ProductA1")); - REQUIRE(IsClass(j, "ProductA2")); - REQUIRE(IsClass(j, "ProductB1")); - REQUIRE(IsClass(j, "ProductB2")); - REQUIRE(IsAbstractClass(j, "AbstractFactory")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsAbstractClass; - - REQUIRE_THAT(src, IsAbstractClass(_A("ProductA"))); - REQUIRE_THAT(src, IsAbstractClass(_A("ProductB"))); - REQUIRE_THAT(src, IsClass(_A("ProductA1"))); - REQUIRE_THAT(src, IsClass(_A("ProductA2"))); - REQUIRE_THAT(src, IsClass(_A("ProductB1"))); - REQUIRE_THAT(src, IsClass(_A("ProductB2"))); - REQUIRE_THAT(src, IsAbstractClass(_A("AbstractFactory"))); - REQUIRE_THAT(src, IsClass(_A("Factory1"))); - REQUIRE_THAT(src, IsClass(_A("Factory2"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsAbstractClass(src, "AbstractFactory")); + REQUIRE(IsAbstractClass(src, "ProductA")); + REQUIRE(IsAbstractClass(src, "ProductB")); + REQUIRE(IsClass(src, "ProductA1")); + REQUIRE(IsClass(src, "ProductA2")); + REQUIRE(IsClass(src, "ProductB1")); + REQUIRE(IsClass(src, "ProductB2")); + REQUIRE(IsClass(src, "Factory1")); + REQUIRE(IsClass(src, "Factory2")); + }); } \ No newline at end of file diff --git a/tests/t00021/test_case.h b/tests/t00021/test_case.h index f916adf3..8b99c173 100644 --- a/tests/t00021/test_case.h +++ b/tests/t00021/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00021/test_case.cc + * tests/t00021/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,59 +16,21 @@ * limitations under the License. */ -TEST_CASE("t00021", "[test-case][class]") +TEST_CASE("t00021") { - auto [config, db] = load_config("t00021"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00021_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00021", "t00021_class"); - REQUIRE(diagram->name == "t00021_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsAbstractClass(src, "Item")); + REQUIRE(IsAbstractClass(src, "Visitor")); + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00021_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsAbstractClass(_A("Item"))); - REQUIRE_THAT(src, IsAbstractClass(_A("Visitor"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("Visitor1"))); - REQUIRE_THAT(src, IsClass(_A("Visitor2"))); - REQUIRE_THAT(src, IsClass(_A("Visitor3"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "Visitor1")); - REQUIRE(IsClass(j, "Visitor2")); - REQUIRE(IsAbstractClass(j, "Item")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsAbstractClass; - - REQUIRE_THAT(src, IsAbstractClass(_A("Item"))); - REQUIRE_THAT(src, IsAbstractClass(_A("Visitor"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("Visitor1"))); - REQUIRE_THAT(src, IsClass(_A("Visitor2"))); - REQUIRE_THAT(src, IsClass(_A("Visitor3"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsClass(src, "Visitor1")); + REQUIRE(IsClass(src, "Visitor2")); + REQUIRE(IsClass(src, "Visitor3")); + }); } \ No newline at end of file diff --git a/tests/t00022/test_case.h b/tests/t00022/test_case.h index ab38da8c..cf060684 100644 --- a/tests/t00022/test_case.h +++ b/tests/t00022/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00022/test_case.cc + * tests/t00022/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,50 +16,16 @@ * limitations under the License. */ -TEST_CASE("t00022", "[test-case][class]") +TEST_CASE("t00022") { - auto [config, db] = load_config("t00022"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00022_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00022", "t00022_class"); - REQUIRE(diagram->name == "t00022_class"); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00022_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsAbstractClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A1"))); - REQUIRE_THAT(src, IsClass(_A("A2"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A1")); - REQUIRE(IsClass(j, "A2")); - REQUIRE(IsAbstractClass(j, "A")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsAbstractClass; - - REQUIRE_THAT(src, IsAbstractClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A1"))); - REQUIRE_THAT(src, IsClass(_A("A2"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A1")); + REQUIRE(IsClass(src, "A2")); + REQUIRE(IsAbstractClass(src, "A")); + }); } diff --git a/tests/t00023/test_case.h b/tests/t00023/test_case.h index a0c74506..14da15a7 100644 --- a/tests/t00023/test_case.h +++ b/tests/t00023/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00023/test_case.cc + * tests/t00023/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,51 +16,16 @@ * limitations under the License. */ -TEST_CASE("t00023", "[test-case][class]") +TEST_CASE("t00023") { - auto [config, db] = load_config("t00023"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00023_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00023", "t00023_class"); - REQUIRE(diagram->name == "t00023_class"); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00023_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsAbstractClass(_A("Strategy"))); - REQUIRE_THAT(src, IsClass(_A("StrategyA"))); - REQUIRE_THAT(src, IsClass(_A("StrategyB"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "StrategyA")); - REQUIRE(IsClass(j, "StrategyB")); - REQUIRE(IsAbstractClass(j, "Strategy")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsAbstractClass; - - REQUIRE_THAT(src, IsAbstractClass(_A("Strategy"))); - REQUIRE_THAT(src, IsClass(_A("StrategyA"))); - REQUIRE_THAT(src, IsClass(_A("StrategyB"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsAbstractClass(src, "Strategy")); + REQUIRE(IsClass(src, "StrategyA")); + REQUIRE(IsClass(src, "StrategyB")); + }); } \ No newline at end of file diff --git a/tests/t00024/test_case.h b/tests/t00024/test_case.h index 7ede8607..c0f79c35 100644 --- a/tests/t00024/test_case.h +++ b/tests/t00024/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00024/test_case.cc + * tests/t00024/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,62 +16,20 @@ * limitations under the License. */ -TEST_CASE("t00024", "[test-case][class]") +TEST_CASE("t00024") { - auto [config, db] = load_config("t00024"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00024_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00024", "t00024_class"); - REQUIRE(diagram->name == "t00024_class"); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00024_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsAbstractClass(_A("Target"))); - REQUIRE_THAT(src, IsClass(_A("Target1"))); - REQUIRE_THAT(src, IsClass(_A("Target2"))); - REQUIRE_THAT(src, IsClass(_A("Proxy"))); - REQUIRE_THAT(src, IsBaseClass(_A("Target"), _A("Target1"))); - REQUIRE_THAT(src, IsBaseClass(_A("Target"), _A("Target2"))); - REQUIRE_THAT(src, IsBaseClass(_A("Target"), _A("Proxy"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "Target1")); - REQUIRE(IsClass(j, "Target2")); - REQUIRE(IsAbstractClass(j, "Target")); - REQUIRE(IsBaseClass(j, "Target", "Target1")); - REQUIRE(IsBaseClass(j, "Target", "Target2")); - REQUIRE(IsBaseClass(j, "Target", "Proxy")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsAbstractClass; - - REQUIRE_THAT(src, IsAbstractClass(_A("Target"))); - REQUIRE_THAT(src, IsClass(_A("Target1"))); - REQUIRE_THAT(src, IsClass(_A("Target2"))); - REQUIRE_THAT(src, IsClass(_A("Proxy"))); - REQUIRE_THAT(src, IsBaseClass(_A("Target"), _A("Target1"))); - REQUIRE_THAT(src, IsBaseClass(_A("Target"), _A("Target2"))); - REQUIRE_THAT(src, IsBaseClass(_A("Target"), _A("Proxy"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "Target1")); + REQUIRE(IsClass(src, "Target2")); + REQUIRE(IsClass(src, "Proxy")); + REQUIRE(IsAbstractClass(src, "Target")); + REQUIRE(IsBaseClass(src, "Target", "Target1")); + REQUIRE(IsBaseClass(src, "Target", "Target2")); + REQUIRE(IsBaseClass(src, "Target", "Proxy")); + }); } \ No newline at end of file diff --git a/tests/t00025/test_case.h b/tests/t00025/test_case.h index c15ba9e9..c6b466a6 100644 --- a/tests/t00025/test_case.h +++ b/tests/t00025/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00025/test_case.cc + * tests/t00025/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,80 +16,29 @@ * limitations under the License. */ -TEST_CASE("t00025", "[test-case][class]") +TEST_CASE("t00025") { - auto [config, db] = load_config("t00025"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00025_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00025", "t00025_class"); - REQUIRE(diagram->name == "t00025_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "Target1")); + REQUIRE(IsClass(src, "Target2")); + REQUIRE(IsClassTemplate(src, "Proxy")); + REQUIRE(IsDependency(src, "Proxy", "Target1")); + REQUIRE(IsDependency(src, "Proxy", "Target2")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00025_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClass(_A("Target1"))); - REQUIRE_THAT(src, IsClass(_A("Target2"))); - REQUIRE_THAT(src, IsClassTemplate("Proxy", "T")); - REQUIRE_THAT( - src, IsInstantiation(_A("Proxy"), _A("Proxy"))); - REQUIRE_THAT( - src, IsInstantiation(_A("Proxy"), _A("Proxy"))); - REQUIRE_THAT(src, - IsAggregation(_A("ProxyHolder"), _A("Proxy"), "+proxy1")); - REQUIRE_THAT(src, - IsAggregation(_A("ProxyHolder"), _A("Proxy"), "+proxy2")); - REQUIRE_THAT( - src, !IsAggregation(_A("ProxyHolder"), _A("Target1"), "+proxy1")); - REQUIRE_THAT( - src, !IsAggregation(_A("ProxyHolder"), _A("Target2"), "+proxy2")); - REQUIRE_THAT(src, IsDependency(_A("Proxy"), _A("Target1"))); - REQUIRE_THAT(src, IsDependency(_A("Proxy"), _A("Target2"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "Target1")); - REQUIRE(IsClass(j, "Target2")); - REQUIRE(IsClassTemplate(j, "Proxy")); - REQUIRE(IsDependency(j, "Proxy", "Target1")); - REQUIRE(IsDependency(j, "Proxy", "Target2")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("Target1"))); - REQUIRE_THAT(src, IsClass(_A("Target2"))); - REQUIRE_THAT(src, IsClass(_A("Proxy"))); - REQUIRE_THAT( - src, IsInstantiation(_A("Proxy"), _A("Proxy"))); - REQUIRE_THAT( - src, IsInstantiation(_A("Proxy"), _A("Proxy"))); - REQUIRE_THAT(src, - IsAggregation(_A("ProxyHolder"), _A("Proxy"), "+proxy1")); - REQUIRE_THAT(src, - IsAggregation(_A("ProxyHolder"), _A("Proxy"), "+proxy2")); - REQUIRE_THAT( - src, !IsAggregation(_A("ProxyHolder"), _A("Target1"), "+proxy1")); - REQUIRE_THAT( - src, !IsAggregation(_A("ProxyHolder"), _A("Target2"), "+proxy2")); - REQUIRE_THAT(src, IsDependency(_A("Proxy"), _A("Target1"))); - REQUIRE_THAT(src, IsDependency(_A("Proxy"), _A("Target2"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsInstantiation(src, "Proxy", "Proxy")); + REQUIRE(IsInstantiation(src, "Proxy", "Proxy")); + REQUIRE(IsAggregation( + src, "ProxyHolder", "Proxy", "proxy1")); + REQUIRE(IsAggregation( + src, "ProxyHolder", "Proxy", "proxy2")); + REQUIRE( + !IsAggregation(src, "ProxyHolder", "Target1", "proxy1")); + REQUIRE( + !IsAggregation(src, "ProxyHolder", "Target2", "proxy2")); + }); } \ No newline at end of file diff --git a/tests/t00026/test_case.h b/tests/t00026/test_case.h index 3de355c2..92349753 100644 --- a/tests/t00026/test_case.h +++ b/tests/t00026/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00026/test_case.cc + * tests/t00026/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,60 +16,22 @@ * limitations under the License. */ -TEST_CASE("t00026", "[test-case][class]") +TEST_CASE("t00026") { - auto [config, db] = load_config("t00026"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00026_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00026", "t00026_class"); - REQUIRE(diagram->name == "t00026_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClassTemplate(src, "Memento")); + REQUIRE(IsClassTemplate(src, "Originator")); + REQUIRE(IsClassTemplate(src, "Caretaker")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00026_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClassTemplate("Memento", "T")); - REQUIRE_THAT(src, IsClassTemplate("Originator", "T")); - REQUIRE_THAT(src, IsClassTemplate("Caretaker", "T")); - REQUIRE_THAT(src, - IsInstantiation( - _A("Originator"), _A("Originator"))); - REQUIRE_THAT(src, - IsInstantiation(_A("Caretaker"), _A("Caretaker"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClassTemplate(j, "Memento")); - REQUIRE(IsClassTemplate(j, "Originator")); - REQUIRE(IsInstantiation(j, "Originator", "Originator")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("Memento"))); - REQUIRE_THAT(src, IsClass(_A("Originator"))); - REQUIRE_THAT(src, IsClass(_A("Caretaker"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("Originator"), _A("Originator"))); - REQUIRE_THAT(src, - IsInstantiation(_A("Caretaker"), _A("Caretaker"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE( + IsInstantiation(src, "Originator", "Originator")); + REQUIRE( + IsInstantiation(src, "Originator", "Originator")); + REQUIRE(IsInstantiation(src, "Caretaker", "Caretaker")); + }); } \ No newline at end of file diff --git a/tests/t00027/test_case.h b/tests/t00027/test_case.h index e9cd07a8..71afe72e 100644 --- a/tests/t00027/test_case.h +++ b/tests/t00027/test_case.h @@ -16,91 +16,34 @@ * limitations under the License. */ -TEST_CASE("t00027", "[test-case][class]") +TEST_CASE("t00027") { - auto [config, db] = load_config("t00027"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00027_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00027", "t00027_class"); - REQUIRE(diagram->name == "t00027_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsAbstractClass(src, "Shape")); + REQUIRE(IsAbstractClass(src, "ShapeDecorator")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClassTemplate(src, "Line...>")); + REQUIRE(IsInstantiation(src, "Line...>", "Line")); + REQUIRE(IsInstantiation(src, "Line...>", "Line")); + REQUIRE( + IsAggregation(src, "Window", "Text", "description")); - REQUIRE(model->name() == "t00027_class"); + REQUIRE(IsInstantiation(src, "Line...>", "Line")); + REQUIRE(IsInstantiation(src, "Line...>", "Line")); + REQUIRE(IsInstantiation(src, "Text...>", "Text")); + REQUIRE(IsInstantiation(src, "Text...>", "Text")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsAbstractClass(_A("Shape"))); - REQUIRE_THAT(src, IsAbstractClass(_A("ShapeDecorator"))); - REQUIRE_THAT(src, IsClassTemplate("Line", "T<>...")); - REQUIRE_THAT(src, IsClassTemplate("Text", "T<>...")); - REQUIRE_THAT( - src, IsInstantiation(_A("Line...>"), _A("Line"))); - REQUIRE_THAT( - src, IsInstantiation(_A("Line...>"), _A("Line"))); - REQUIRE_THAT( - src, IsInstantiation(_A("Text...>"), _A("Text"))); - REQUIRE_THAT( - src, IsInstantiation(_A("Text...>"), _A("Text"))); - - REQUIRE_THAT(src, - IsAggregation(_A("Window"), _A("Line"), "+border")); - REQUIRE_THAT( - src, IsAggregation(_A("Window"), _A("Line"), "+divider")); - REQUIRE_THAT(src, - IsAggregation(_A("Window"), _A("Text"), "+title")); - REQUIRE_THAT(src, - IsAggregation(_A("Window"), _A("Text"), "+description")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsAbstractClass(j, "Shape")); - REQUIRE(IsAbstractClass(j, "ShapeDecorator")); - - REQUIRE(IsClassTemplate(j, "Line...>")); - REQUIRE(IsInstantiation(j, "Line...>", "Line")); - REQUIRE(IsInstantiation(j, "Line...>", "Line")); - REQUIRE(IsAggregation(j, "Window", "Text", "description")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsAbstractClass; - - REQUIRE_THAT(src, IsAbstractClass(_A("Shape"))); - REQUIRE_THAT(src, IsAbstractClass(_A("ShapeDecorator"))); - REQUIRE_THAT(src, IsClass(_A("Line...>"))); - REQUIRE_THAT(src, IsClass(_A("Text...>"))); - REQUIRE_THAT( - src, IsInstantiation(_A("Line...>"), _A("Line"))); - REQUIRE_THAT( - src, IsInstantiation(_A("Line...>"), _A("Line"))); - REQUIRE_THAT( - src, IsInstantiation(_A("Text...>"), _A("Text"))); - REQUIRE_THAT( - src, IsInstantiation(_A("Text...>"), _A("Text"))); - - REQUIRE_THAT(src, - IsAggregation(_A("Window"), _A("Line"), "+border")); - REQUIRE_THAT( - src, IsAggregation(_A("Window"), _A("Line"), "+divider")); - REQUIRE_THAT(src, - IsAggregation(_A("Window"), _A("Text"), "+title")); - REQUIRE_THAT(src, - IsAggregation(_A("Window"), _A("Text"), "+description")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAggregation( + src, "Window", "Line", "border")); + REQUIRE(IsAggregation(src, "Window", "Line", "divider")); + REQUIRE(IsAggregation( + src, "Window", "Text", "title")); + REQUIRE( + IsAggregation(src, "Window", "Text", "description")); + }); } \ No newline at end of file diff --git a/tests/t00028/test_case.h b/tests/t00028/test_case.h index 77b8df35..ad2860b0 100644 --- a/tests/t00028/test_case.h +++ b/tests/t00028/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00028/test_case.cc + * tests/t00028/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,90 +16,44 @@ * limitations under the License. */ -TEST_CASE("t00028", "[test-case][class]") +TEST_CASE("t00028") { - auto [config, db] = load_config("t00028"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00028_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00028", "t00028_class"); - REQUIRE(diagram->name == "t00028_class"); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00028_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClassTemplate("E", "T")); - REQUIRE_THAT(src, IsEnum(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - REQUIRE_THAT(src, HasNote(_A("A"), "top", "A class note.")); - REQUIRE_THAT(src, HasNote(_A("B"), "left", "B class note.")); - REQUIRE_THAT(src, HasNote(_A("C"), "bottom", "C class note.")); - const auto d_note = R"( + CHECK_CLASS_DIAGRAM( + config, diagram, *model, + [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClassTemplate(src, "E")); + REQUIRE(IsEnum(src, "F")); + REQUIRE(IsClass(src, "R")); + REQUIRE(HasNote(src, "A", "top", "A class note.")); + REQUIRE(HasNote(src, "B", "left", "B class note.")); + REQUIRE(HasNote(src, "C", "bottom", "C class note.")); + const auto d_note = R"( D class note.)"; - REQUIRE_THAT(src, HasNote(_A("D"), "left", d_note)); - REQUIRE_THAT( - src, HasNote(_A("E"), "left", "E template class note.")); - REQUIRE_THAT(src, HasNote(_A("F"), "bottom", "F enum note.")); - REQUIRE_THAT(src, !HasNote(_A("G"), "left", "G class note.")); - REQUIRE_THAT(src, HasNote(_A("R"), "right", "R class note.")); - REQUIRE_THAT(src, - HasMemberNote( - _A("R"), "aaa", "left", "R contains an instance of A.")); - REQUIRE_THAT( - src, !HasMemberNote(_A("R"), "bbb", "right", "R class note.")); - REQUIRE_THAT( - src, HasMemberNote(_A("R"), "ccc", "left", "Reference to C.")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::HasNote; - using mermaid::IsEnum; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsEnum(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - REQUIRE_THAT(src, HasNote(_A("A"), "top", "A class note.")); - REQUIRE_THAT(src, HasNote(_A("B"), "left", "B class note.")); - REQUIRE_THAT(src, HasNote(_A("C"), "bottom", "C class note.")); - const auto d_note = R"( -D -class -note.)"; - REQUIRE_THAT(src, HasNote(_A("D"), "left", d_note)); - REQUIRE_THAT( - src, HasNote(_A("E"), "left", "E template class note.")); - REQUIRE_THAT(src, HasNote(_A("F"), "bottom", "F enum note.")); - REQUIRE_THAT(src, !HasNote(_A("G"), "left", "G class note.")); - REQUIRE_THAT(src, HasNote(_A("R"), "right", "R class note.")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(HasNote(src, "D", "left", d_note)); + REQUIRE(HasNote(src, "E", "left", "E template class note.")); + REQUIRE(HasNote(src, "F", "bottom", "F enum note.")); + REQUIRE(HasNote(src, "R", "right", "R class note.")); + }, + [](const plantuml_t &src) { + REQUIRE(HasMemberNote(src, "R", "ccc", "left", "Reference to C.")); + REQUIRE(!HasMemberNote(src, "R", "bbb", "right", "R class note.")); + REQUIRE(HasMemberNote( + src, "R", "aaa", "left", "R contains an instance of A.")); + REQUIRE(!HasNote(src, "G", "left", "G class note.")); + }, + [](const mermaid_t &src) { + REQUIRE(HasNote(src, "R", "left", "R contains an instance of A.")); + REQUIRE(!HasNote(src, "G", "left", "G class note.")); + }); } \ No newline at end of file diff --git a/tests/t00029/test_case.h b/tests/t00029/test_case.h index c5ed006b..4d969d1d 100644 --- a/tests/t00029/test_case.h +++ b/tests/t00029/test_case.h @@ -16,78 +16,32 @@ * limitations under the License. */ -TEST_CASE("t00029", "[test-case][class]") +TEST_CASE("t00029") { - auto [config, db] = load_config("t00029"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00029_class"]; - - REQUIRE(diagram->name == "t00029_class"); - - auto model = generate_class_diagram(*db, diagram); + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00029", "t00029_class"); REQUIRE(model->name() == "t00029_class"); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(!IsClass(src, "B")); + REQUIRE(IsClassTemplate(src, "C")); + REQUIRE(!IsClassTemplate(src, "D")); + REQUIRE(IsEnum(src, "E")); + REQUIRE(!IsEnum(src, "F")); + REQUIRE(IsClass(src, "G1")); + REQUIRE(IsClass(src, "G2")); + REQUIRE(IsClass(src, "G3")); + REQUIRE(IsClass(src, "G4")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(IsClass(src, "R")); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, !IsClass(_A("B"))); - REQUIRE_THAT(src, IsClassTemplate("C", "T")); - REQUIRE_THAT(src, !IsClassTemplate("D", "T")); - REQUIRE_THAT(src, IsEnum(_A("E"))); - REQUIRE_THAT(src, !IsEnum(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G1"))); - REQUIRE_THAT(src, IsClass(_A("G2"))); - REQUIRE_THAT(src, IsClass(_A("G3"))); - REQUIRE_THAT(src, IsClass(_A("G4"))); - - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("G1"), "+g1")); - REQUIRE_THAT(src, !IsAggregation(_A("R"), _A("G2"), "+g2")); - REQUIRE_THAT(src, !IsAggregation(_A("R"), _A("G3"), "+g3")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("G4"), "+g4")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsAggregation(j, "R", "G1", "g1")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsEnum; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, !IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, !IsClass(_A("D"))); - REQUIRE_THAT(src, IsEnum(_A("E"))); - REQUIRE_THAT(src, !IsEnum(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G1"))); - REQUIRE_THAT(src, IsClass(_A("G2"))); - REQUIRE_THAT(src, IsClass(_A("G3"))); - REQUIRE_THAT(src, IsClass(_A("G4"))); - - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("G1"), "+g1")); - REQUIRE_THAT(src, !IsAggregation(_A("R"), _A("G2"), "+g2")); - REQUIRE_THAT(src, !IsAggregation(_A("R"), _A("G3"), "+g3")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("G4"), "+g4")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAggregation(src, "R", "G1", "g1")); + REQUIRE(!IsAggregation(src, "R", "G2", "g2")); + REQUIRE(!IsAggregation(src, "R", "G3", "g3")); + REQUIRE(IsAssociation(src, "R", "G4", "g4")); + }); } \ No newline at end of file diff --git a/tests/t00030/test_case.h b/tests/t00030/test_case.h index bd04683e..f51dbd1c 100644 --- a/tests/t00030/test_case.h +++ b/tests/t00030/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00030/test_case.cc + * tests/t00030/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,67 +16,23 @@ * limitations under the License. */ -TEST_CASE("t00030", "[test-case][class]") +TEST_CASE("t00030") { - auto [config, db] = load_config("t00030"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00030_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00030", "t00030_class"); - REQUIRE(diagram->name == "t00030_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00030_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("A"), "+aaa")); - REQUIRE_THAT( - src, IsComposition(_A("R"), _A("B"), "+bbb", "0..1", "1..*")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("C"), "+ccc", "0..1", "1..5")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("D"), "+ddd", "", "1")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("E"), "+eee", "", "1")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsAggregation(j, "R", "C", "ccc")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("A"), "+aaa")); - REQUIRE_THAT( - src, IsComposition(_A("R"), _A("B"), "+bbb", "0..1", "1..*")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("C"), "+ccc", "0..1", "1..5")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("D"), "+ddd", "", "1")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("E"), "+eee", "", "1")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAssociation(src, "R", "A", "aaa")); + REQUIRE(IsComposition(src, "R", "B", "bbb", "0..1", "1..*")); + REQUIRE(IsAggregation(src, "R", "C", "ccc", "0..1", "1..5")); + REQUIRE(IsAssociation(src, "R", "D", "ddd", "", "1")); + REQUIRE(IsAggregation(src, "R", "E", "eee", "", "1")); + }); } \ No newline at end of file diff --git a/tests/t00031/test_case.h b/tests/t00031/test_case.h index d4ab8482..c3f873dd 100644 --- a/tests/t00031/test_case.h +++ b/tests/t00031/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00031/test_case.cc + * tests/t00031/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,67 +16,27 @@ * limitations under the License. */ -TEST_CASE("t00031", "[test-case][class]") +TEST_CASE("t00031") { - auto [config, db] = load_config("t00031"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00031_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00031", "t00031_class"); - REQUIRE(diagram->name == "t00031_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsEnum(src, "B")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClassTemplate(src, "C")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00031_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsEnum(_A("B"))); - REQUIRE_THAT(src, IsClassTemplate("C", "T")); - REQUIRE_THAT(src, IsClass(_A("D"))); - - REQUIRE_THAT(src, - IsAssociation( - _A("R"), _A("A"), "+aaa", "", "", "[#red,dashed,thickness=2]")); - REQUIRE_THAT(src, - IsComposition(_A("R"), _A("B"), "+bbb", "", "", - "[#green,dashed,thickness=4]")); - REQUIRE_THAT(src, IsDependency(_A("R"), _A("B"))); - REQUIRE_THAT(src, - IsAggregation(_A("R"), _A("C"), "+ccc", "", "", - "[#blue,dotted,thickness=8]")); - REQUIRE_THAT(src, - IsAssociation(_A("R"), _A("D"), "+ddd", "", "", - "[#blue,plain,thickness=16]")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClassTemplate(j, "C")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsEnum; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsEnum(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAssociation( + src, "R", "A", "aaa", "", "", "[#red,dashed,thickness=2]")); + REQUIRE(IsComposition( + src, "R", "B", "bbb", "", "", "[#green,dashed,thickness=4]")); + REQUIRE(IsDependency(src, "R", "B")); + REQUIRE(IsAggregation( + src, "R", "C", "ccc", "", "", "[#blue,dotted,thickness=8]")); + REQUIRE(IsAssociation( + src, "R", "D", "ddd", "", "", "[#blue,plain,thickness=16]")); + }); } \ No newline at end of file diff --git a/tests/t00032/test_case.h b/tests/t00032/test_case.h index 09dad790..59582dfa 100644 --- a/tests/t00032/test_case.h +++ b/tests/t00032/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00032/test_case.cc + * tests/t00032/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,95 +16,31 @@ * limitations under the License. */ -TEST_CASE("t00032", "[test-case][class]") +TEST_CASE("t00032") { - auto [config, db] = load_config("t00032"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00032_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00032", "t00032_class"); - REQUIRE(diagram->name == "t00032_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "Base")); + REQUIRE(IsClass(src, "TBase")); + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "R")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClassTemplate(src, "Overload")); - REQUIRE(model->name() == "t00032_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("Base"))); - REQUIRE_THAT(src, IsClass(_A("TBase"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsClassTemplate("Overload", "T,L,Ts...")); - - REQUIRE_THAT(src, IsBaseClass(_A("Base"), _A("Overload"))); - REQUIRE_THAT( - src, IsBaseClass(_A("TBase"), _A("Overload"))); - REQUIRE_THAT( - src, IsBaseClass(_A("A"), _A("Overload"))); - REQUIRE_THAT( - src, IsBaseClass(_A("B"), _A("Overload"))); - REQUIRE_THAT( - src, IsBaseClass(_A("C"), _A("Overload"))); - REQUIRE_THAT( - src, !IsDependency(_A("Overload"), _A("TBase"))); - REQUIRE_THAT( - src, !IsDependency(_A("Overload"), _A("A"))); - REQUIRE_THAT( - src, !IsDependency(_A("Overload"), _A("B"))); - REQUIRE_THAT( - src, !IsDependency(_A("Overload"), _A("C"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsBaseClass(j, "A", "Overload")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("Base"))); - REQUIRE_THAT(src, IsClass(_A("TBase"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsClass(_A("Overload"))); - - REQUIRE_THAT(src, IsBaseClass(_A("Base"), _A("Overload"))); - REQUIRE_THAT( - src, IsBaseClass(_A("TBase"), _A("Overload"))); - REQUIRE_THAT( - src, IsBaseClass(_A("A"), _A("Overload"))); - REQUIRE_THAT( - src, IsBaseClass(_A("B"), _A("Overload"))); - REQUIRE_THAT( - src, IsBaseClass(_A("C"), _A("Overload"))); - REQUIRE_THAT( - src, !IsDependency(_A("Overload"), _A("TBase"))); - REQUIRE_THAT( - src, !IsDependency(_A("Overload"), _A("A"))); - REQUIRE_THAT( - src, !IsDependency(_A("Overload"), _A("B"))); - REQUIRE_THAT( - src, !IsDependency(_A("Overload"), _A("C"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsBaseClass(src, "Base", "Overload")); + REQUIRE(IsBaseClass(src, "TBase", "Overload")); + REQUIRE(IsBaseClass(src, "A", "Overload")); + REQUIRE(IsBaseClass(src, "B", "Overload")); + REQUIRE(IsBaseClass(src, "C", "Overload")); + REQUIRE(!IsDependency(src, "Overload", "TBase")); + REQUIRE(!IsDependency(src, "Overload", "A")); + REQUIRE(!IsDependency(src, "Overload", "B")); + REQUIRE(!IsDependency(src, "Overload", "C")); + }); } \ No newline at end of file diff --git a/tests/t00033/test_case.h b/tests/t00033/test_case.h index d5fdd3e7..b5cca187 100644 --- a/tests/t00033/test_case.h +++ b/tests/t00033/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00033/test_case.cc + * tests/t00033/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,82 +16,28 @@ * limitations under the License. */ -TEST_CASE("t00033", "[test-case][class]") +TEST_CASE("t00033") { - auto [config, db] = load_config("t00033"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00033_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00033", "t00033_class"); - REQUIRE(diagram->name == "t00033_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "B")); + REQUIRE(IsClassTemplate(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClass(src, "R")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00033_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClassTemplate("A", "T")); - REQUIRE_THAT(src, IsClassTemplate("B", "T")); - REQUIRE_THAT(src, IsClassTemplate("C", "T")); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, - IsDependency(_A("A>>>"), - _A("B>>"))); - REQUIRE_THAT( - src, IsDependency(_A("B>>"), _A("C"))); - REQUIRE_THAT(src, IsDependency(_A("C"), _A("D"))); - - REQUIRE_THAT(src, IsInstantiation(_A("C"), _A("C"), "up")); - REQUIRE_THAT(src, - IsInstantiation(_A("B"), _A("B>>"), "up")); - REQUIRE_THAT(src, - IsInstantiation( - _A("A"), _A("A>>>"), "up")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A>>>")); REQUIRE(IsDependency( - j, "A>>>", "B>>")); + src, "A>>>", "B>>")); + REQUIRE(IsDependency(src, "B>>", "C")); + REQUIRE(IsDependency(src, "C", "D")); - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, - IsDependency(_A("A>>>"), - _A("B>>"))); - REQUIRE_THAT( - src, IsDependency(_A("B>>"), _A("C"))); - REQUIRE_THAT(src, IsDependency(_A("C"), _A("D"))); - - REQUIRE_THAT(src, IsInstantiation(_A("C"), _A("C"))); - REQUIRE_THAT( - src, IsInstantiation(_A("B"), _A("B>>"))); - REQUIRE_THAT(src, - IsInstantiation(_A("A"), _A("A>>>"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsInstantiation(src, "C", "C", "up")); + REQUIRE(IsInstantiation(src, "B", "B>>", "up")); + REQUIRE( + IsInstantiation(src, "A", "A>>>", "up")); + }); } \ No newline at end of file diff --git a/tests/t00034/test_case.h b/tests/t00034/test_case.h index 8a6858f7..45040d82 100644 --- a/tests/t00034/test_case.h +++ b/tests/t00034/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00034/test_case.cc + * tests/t00034/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,64 +16,21 @@ * limitations under the License. */ -TEST_CASE("t00034", "[test-case][class]") +TEST_CASE("t00034") { - auto [config, db] = load_config("t00034"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00034_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00034", "t00034_class"); - REQUIRE(diagram->name == "t00034_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClassTemplate(src, "lift_void")); + REQUIRE(IsClassTemplate(src, "drop_void")); + REQUIRE(IsClass(src, "Void")); + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "R")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00034_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClassTemplate("lift_void", "T")); - REQUIRE_THAT(src, IsClassTemplate("drop_void", "T")); - REQUIRE_THAT(src, IsClass(_A("Void"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT( - src, IsInstantiation(_A("lift_void"), _A("lift_void"))); - REQUIRE_THAT( - src, IsInstantiation(_A("drop_void"), _A("drop_void"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClassTemplate(j, "lift_void")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("lift_void"))); - REQUIRE_THAT(src, IsClass(_A("drop_void"))); - REQUIRE_THAT(src, IsClass(_A("Void"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT( - src, IsInstantiation(_A("lift_void"), _A("lift_void"))); - REQUIRE_THAT( - src, IsInstantiation(_A("drop_void"), _A("drop_void"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsInstantiation(src, "lift_void", "lift_void")); + REQUIRE(IsInstantiation(src, "drop_void", "drop_void")); + }); } \ No newline at end of file diff --git a/tests/t00035/test_case.h b/tests/t00035/test_case.h index 51018e78..02d63311 100644 --- a/tests/t00035/test_case.h +++ b/tests/t00035/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00035/test_case.cc + * tests/t00035/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,62 +16,23 @@ * limitations under the License. */ -TEST_CASE("t00035", "[test-case][class]") +TEST_CASE("t00035") { - auto [config, db] = load_config("t00035"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00035_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00035", "t00035_class"); - REQUIRE(diagram->name == "t00035_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "Top")); + REQUIRE(IsClass(src, "Bottom")); + REQUIRE(IsClass(src, "Center")); + REQUIRE(IsClass(src, "Left")); + REQUIRE(IsClass(src, "Right")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00035_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("Top"))); - REQUIRE_THAT(src, IsClass(_A("Bottom"))); - REQUIRE_THAT(src, IsClass(_A("Center"))); - REQUIRE_THAT(src, IsClass(_A("Left"))); - REQUIRE_THAT(src, IsClass(_A("Right"))); - - REQUIRE_THAT(src, IsLayoutHint(_A("Center"), "up", _A("Top"))); - REQUIRE_THAT(src, IsLayoutHint(_A("Center"), "left", _A("Left"))); - REQUIRE_THAT(src, IsLayoutHint(_A("Center"), "right", _A("Right"))); - REQUIRE_THAT(src, IsLayoutHint(_A("Center"), "down", _A("Bottom"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "Top")); - REQUIRE(IsClass(j, "Bottom")); - REQUIRE(IsClass(j, "Center")); - REQUIRE(IsClass(j, "Left")); - REQUIRE(IsClass(j, "Right")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("Top"))); - REQUIRE_THAT(src, IsClass(_A("Bottom"))); - REQUIRE_THAT(src, IsClass(_A("Center"))); - REQUIRE_THAT(src, IsClass(_A("Left"))); - REQUIRE_THAT(src, IsClass(_A("Right"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsLayoutHint(src, "Center", "up", "Top")); + REQUIRE(IsLayoutHint(src, "Center", "left", "Left")); + REQUIRE(IsLayoutHint(src, "Center", "right", "Right")); + REQUIRE(IsLayoutHint(src, "Center", "down", "Bottom")); + }); } \ No newline at end of file diff --git a/tests/t00036/test_case.h b/tests/t00036/test_case.h index 12c58572..6e44a5d9 100644 --- a/tests/t00036/test_case.h +++ b/tests/t00036/test_case.h @@ -16,79 +16,33 @@ * limitations under the License. */ -TEST_CASE("t00036", "[test-case][class]") +TEST_CASE("t00036") { - auto [config, db] = load_config("t00036"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t00036_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00036", "t00036_class"); - REQUIRE(diagram->name == "t00036_class"); REQUIRE(diagram->generate_packages() == true); - auto model = generate_class_diagram(*db, diagram); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClassTemplate(src, {"ns1::ns11", "A"})); + REQUIRE(IsClassTemplate(src, {"ns1::ns11", "A"})); + REQUIRE(IsClass(src, {"ns1::ns11::ns111", "B"})); + REQUIRE(IsClass(src, {"ns2::ns22", "C"})); + REQUIRE(IsEnum(src, {"ns1", "E"})); - REQUIRE(model->name() == "t00036_class"); + REQUIRE(!IsClass(src, "DImpl")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsNamespacePackage(src, "ns1"s)); + REQUIRE(IsNamespacePackage(src, "ns1"s, "ns11"s)); + REQUIRE(IsNamespacePackage(src, "ns1"s, "ns11"s, "ns111"s)); + REQUIRE(IsNamespacePackage(src, "ns2"s)); + REQUIRE(IsNamespacePackage(src, "ns2"s, "ns22"s)); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClassTemplate("A", "T")); - REQUIRE_THAT(src, IsClassTemplate("A", "int")); - REQUIRE_THAT(src, IsEnum(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, !IsClass(_A("DImpl"))); - REQUIRE_THAT(src, IsPackage("ns111")); - REQUIRE_THAT(src, IsPackage("ns22")); - REQUIRE_THAT(src, !IsPackage("ns3")); - REQUIRE_THAT(src, !IsPackage("ns33")); - - REQUIRE_THAT(src, IsAggregation(_A("B"), _A("A"), "+a_int")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsClass(j, "ns1::ns11::A")); - REQUIRE(IsClass(j, "ns1::ns11::A")); - REQUIRE(IsClass(j, "ns1::ns11::ns111::B")); - REQUIRE(IsClass(j, "ns2::ns22::C")); - REQUIRE(IsEnum(j, "ns1::E")); - REQUIRE(IsNamespacePackage(j, "ns1"s)); - REQUIRE(IsNamespacePackage(j, "ns1"s, "ns11"s)); - REQUIRE(IsNamespacePackage(j, "ns1"s, "ns11"s, "ns111"s)); - REQUIRE(IsNamespacePackage(j, "ns2"s)); - REQUIRE(IsNamespacePackage(j, "ns2"s, "ns22"s)); - REQUIRE(IsNamespacePackage(j, "ns3"s)); - REQUIRE(IsNamespacePackage(j, "ns3"s, "ns33"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsEnum; - - REQUIRE_THAT(src, IsClass(_A("ns1::ns11::A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns11::A"))); - REQUIRE_THAT(src, IsEnum(_A("ns1::E"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns11::ns111::B"))); - REQUIRE_THAT(src, IsClass(_A("ns2::ns22::C"))); - REQUIRE_THAT(src, !IsClass(_A("DImpl"))); - - REQUIRE_THAT(src, - IsAggregation( - _A("ns1::ns11::ns111::B"), _A("ns1::ns11::A"), "+a_int")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!IsNamespacePackage(src, "ns3"s)); + REQUIRE(!IsNamespacePackage(src, "ns33"s)); + REQUIRE(!IsNamespacePackage(src, "ns3"s, "ns33"s)); + }); } \ No newline at end of file diff --git a/tests/t00037/test_case.h b/tests/t00037/test_case.h index e5e62d0f..662bccbc 100644 --- a/tests/t00037/test_case.h +++ b/tests/t00037/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00037/test_case.cc + * tests/t00037/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,62 +16,23 @@ * limitations under the License. */ -TEST_CASE("t00037", "[test-case][class]") +TEST_CASE("t00037") { - auto [config, db] = load_config("t00037"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00037_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00037", "t00037_class"); - REQUIRE(diagram->name == "t00037_class"); REQUIRE(diagram->generate_packages() == true); - auto model = generate_class_diagram(*db, diagram); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "ST")); + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "ST::(units)")); + REQUIRE(IsClass(src, "ST::(dimensions)")); - REQUIRE(model->name() == "t00037_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("ST"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("ST::(units)"))); - REQUIRE_THAT(src, IsClass(_A("ST::(dimensions)"))); - REQUIRE_THAT(src, - IsAggregation(_A("ST"), _A("ST::(dimensions)"), "+dimensions")); - REQUIRE_THAT(src, IsAggregation(_A("ST"), _A("ST::(units)"), "-units")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "ST")); - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "ST::(units)")); - REQUIRE(IsClass(j, "ST::(dimensions)")); - REQUIRE(IsAggregation(j, "ST", "ST::(dimensions)", "dimensions")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("ST"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("ST::(units)"))); - REQUIRE_THAT(src, IsClass(_A("ST::(dimensions)"))); - REQUIRE_THAT(src, - IsAggregation(_A("ST"), _A("ST::(dimensions)"), "+dimensions")); - REQUIRE_THAT(src, IsAggregation(_A("ST"), _A("ST::(units)"), "-units")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE( + IsAggregation(src, "ST", "ST::(dimensions)", "dimensions")); + REQUIRE(IsAggregation(src, "ST", "ST::(units)", "units")); + }); } \ No newline at end of file diff --git a/tests/t00038/test_case.h b/tests/t00038/test_case.h index 38363ddc..ae900531 100644 --- a/tests/t00038/test_case.h +++ b/tests/t00038/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00038/test_case.cc + * tests/t00038/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,165 +16,63 @@ * limitations under the License. */ -TEST_CASE("t00038", "[test-case][class]") +TEST_CASE("t00038") { - auto [config, db] = load_config("t00038"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00038_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00038", "t00038_class"); - REQUIRE(diagram->name == "t00038_class"); - REQUIRE(diagram->generate_packages() == false); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "thirdparty::ns1::E")); + REQUIRE(IsClass(src, "key_t")); + REQUIRE(IsClassTemplate(src, "map")); + REQUIRE(IsClassTemplate(src, + "map>")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClassTemplate(src, + "map>>")); + REQUIRE(IsClassTemplate(src, + "map>>>")); - REQUIRE(model->name() == "t00038_class"); + REQUIRE(IsEnum(src, "property_t")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsInstantiation(src, "map", + "map>>>")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(IsDependency(src, + "map>", + "property_t")); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("thirdparty::ns1::E"))); - REQUIRE_THAT(src, IsClass(_A("key_t"))); - REQUIRE_THAT(src, IsClassTemplate("map", "T")); - REQUIRE_THAT(src, - IsClassTemplate("map", - "std::integral_constant")); - REQUIRE_THAT(src, - IsClassTemplate("map", - "std::vector>")); - REQUIRE_THAT(src, - IsClassTemplate("map", - "std::map>>")); + REQUIRE(IsDependency(src, + "map<" + "std::vector>>", + "property_t")); - REQUIRE_THAT(src, IsEnum(_A("property_t"))); + REQUIRE(IsDependency(src, + "map>>>", + "property_t")); - REQUIRE_THAT(src, - IsInstantiation(_A("map"), - _A("map>>>"))); + REQUIRE(IsDependency(src, + "map>>>", + "key_t")); - REQUIRE_THAT(src, - IsDependency(_A("map>"), - _A("property_t"))); + REQUIRE(IsDependency(src, + "map>", + "thirdparty::ns1::color_t")); - REQUIRE_THAT(src, - IsDependency(_A("map<" - "std::vector>>"), - _A("property_t"))); - - REQUIRE_THAT(src, - IsDependency( - _A("map>>>"), - _A("property_t"))); - - REQUIRE_THAT(src, - IsDependency( - _A("map>>>"), - _A("key_t"))); - - REQUIRE_THAT(src, - IsDependency( - _A("map>"), - _A("thirdparty::ns1::color_t"))); - - REQUIRE_THAT(src, - IsBaseClass(_A("thirdparty::ns1::E"), - _A("map>"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsEnum; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("thirdparty::ns1::E"))); - REQUIRE_THAT(src, IsClass(_A("key_t"))); - REQUIRE_THAT(src, IsClass(_A("map"))); - REQUIRE_THAT(src, - IsClass(_A("map>"))); - REQUIRE_THAT(src, - IsClass(_A( - "map>>"))); - REQUIRE_THAT(src, - IsClass(_A("map>>>"))); - - REQUIRE_THAT(src, IsEnum(_A("property_t"))); - - REQUIRE_THAT(src, - IsInstantiation(_A("map"), - _A("map>>>"))); - - REQUIRE_THAT(src, - IsDependency(_A("map>"), - _A("property_t"))); - - REQUIRE_THAT(src, - IsDependency(_A("map<" - "std::vector>>"), - _A("property_t"))); - - REQUIRE_THAT(src, - IsDependency( - _A("map>>>"), - _A("property_t"))); - - REQUIRE_THAT(src, - IsDependency( - _A("map>>>"), - _A("key_t"))); - - REQUIRE_THAT(src, - IsDependency( - _A("map>"), - _A("thirdparty::ns1::color_t"))); - - REQUIRE_THAT(src, - IsBaseClass(_A("thirdparty::ns1::E"), - _A("map>"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsBaseClass(src, "thirdparty::ns1::E", + "map>")); + }); } \ No newline at end of file diff --git a/tests/t00039/test_case.h b/tests/t00039/test_case.h index 9e4c562b..1d722056 100644 --- a/tests/t00039/test_case.h +++ b/tests/t00039/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00039/test_case.cc + * tests/t00039/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,108 +16,40 @@ * limitations under the License. */ -TEST_CASE("t00039", "[test-case][class]") +TEST_CASE("t00039") { - auto [config, db] = load_config("t00039"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00039_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00039", "t00039_class"); - REQUIRE(diagram->name == "t00039_class"); - REQUIRE(diagram->generate_packages() == false); - auto model = generate_class_diagram(*db, diagram); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "AA")); + REQUIRE(IsClass(src, "AAA")); + REQUIRE(IsClass(src, "ns2::AAAA")); + REQUIRE(IsBaseClass(src, "A", "AA")); + REQUIRE(IsBaseClass(src, "AA", "AAA")); + REQUIRE(IsBaseClass(src, "AAA", "ns2::AAAA")); + REQUIRE(!IsClass(src, "detail::AA")); - REQUIRE(model->name() == "t00039_class"); + REQUIRE(!IsClass(src, "B")); + REQUIRE(!IsClass(src, "ns1::BB")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClass(src, "E")); + REQUIRE(IsBaseClass(src, "C", "CD")); + REQUIRE(IsBaseClass(src, "D", "CD")); + REQUIRE(IsBaseClass(src, "D", "DE")); + REQUIRE(IsBaseClass(src, "E", "DE")); + REQUIRE(IsBaseClass(src, "C", "CDE")); + REQUIRE(IsBaseClass(src, "D", "CDE")); + REQUIRE(IsBaseClass(src, "E", "CDE")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("AAA"))); - REQUIRE_THAT(src, IsClass(_A("ns2::AAAA"))); - REQUIRE_THAT(src, IsBaseClass(_A("A"), _A("AA"))); - REQUIRE_THAT(src, IsBaseClass(_A("AA"), _A("AAA"))); - REQUIRE_THAT(src, IsBaseClass(_A("AAA"), _A("ns2::AAAA"))); - REQUIRE_THAT(src, !IsClass(_A("detail::AA"))); - - REQUIRE_THAT(src, !IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("ns1::BB"))); - - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsBaseClass(_A("C"), _A("CD"))); - REQUIRE_THAT(src, IsBaseClass(_A("D"), _A("CD"))); - REQUIRE_THAT(src, IsBaseClass(_A("D"), _A("DE"))); - REQUIRE_THAT(src, IsBaseClass(_A("E"), _A("DE"))); - REQUIRE_THAT(src, IsBaseClass(_A("C"), _A("CDE"))); - REQUIRE_THAT(src, IsBaseClass(_A("D"), _A("CDE"))); - REQUIRE_THAT(src, IsBaseClass(_A("E"), _A("CDE"))); - - REQUIRE_THAT(src, IsClassTemplate("ns3::F", "T")); - REQUIRE_THAT(src, IsClassTemplate("ns3::FF", "T,M")); - REQUIRE_THAT(src, IsClassTemplate("ns3::FE", "T,M")); - REQUIRE_THAT(src, IsClassTemplate("ns3::FFF", "T,M,N")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "AA")); - REQUIRE(IsClass(j, "AAA")); - REQUIRE(IsBaseClass(j, "C", "CD")); - REQUIRE(IsBaseClass(j, "D", "CD")); - REQUIRE(IsBaseClass(j, "E", "DE")); - REQUIRE(IsBaseClass(j, "D", "DE")); - REQUIRE(IsBaseClass(j, "C", "CDE")); - REQUIRE(IsBaseClass(j, "D", "CDE")); - REQUIRE(IsBaseClass(j, "E", "CDE")); - - REQUIRE(IsClassTemplate(j, "ns3::F")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("AAA"))); - REQUIRE_THAT(src, IsClass(_A("ns2::AAAA"))); - REQUIRE_THAT(src, IsBaseClass(_A("A"), _A("AA"))); - REQUIRE_THAT(src, IsBaseClass(_A("AA"), _A("AAA"))); - REQUIRE_THAT(src, IsBaseClass(_A("AAA"), _A("ns2::AAAA"))); - REQUIRE_THAT(src, !IsClass(_A("detail::AA"))); - - REQUIRE_THAT(src, !IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("ns1::BB"))); - - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsBaseClass(_A("C"), _A("CD"))); - REQUIRE_THAT(src, IsBaseClass(_A("D"), _A("CD"))); - REQUIRE_THAT(src, IsBaseClass(_A("D"), _A("DE"))); - REQUIRE_THAT(src, IsBaseClass(_A("E"), _A("DE"))); - REQUIRE_THAT(src, IsBaseClass(_A("C"), _A("CDE"))); - REQUIRE_THAT(src, IsBaseClass(_A("D"), _A("CDE"))); - REQUIRE_THAT(src, IsBaseClass(_A("E"), _A("CDE"))); - - REQUIRE_THAT(src, IsClass(_A("ns3::F"))); - REQUIRE_THAT(src, IsClass(_A("ns3::FF"))); - REQUIRE_THAT(src, IsClass(_A("ns3::FE"))); - REQUIRE_THAT(src, IsClass(_A("ns3::FFF"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsClassTemplate(src, "ns3::F")); + REQUIRE(IsClassTemplate(src, "ns3::FF")); + REQUIRE(IsClassTemplate(src, "ns3::FE")); + REQUIRE(IsClassTemplate(src, "ns3::FFF")); + }); } diff --git a/tests/t00040/test_case.h b/tests/t00040/test_case.h index ec8b0181..d5915b71 100644 --- a/tests/t00040/test_case.h +++ b/tests/t00040/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00040/test_case.cc + * tests/t00040/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,63 +16,20 @@ * limitations under the License. */ -TEST_CASE("t00040", "[test-case][class]") +TEST_CASE("t00040") { - auto [config, db] = load_config("t00040"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00040_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00040", "t00040_class"); - REQUIRE(diagram->name == "t00040_class"); - REQUIRE(diagram->generate_packages() == false); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00040_class"); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("AAA"))); - REQUIRE_THAT(src, IsBaseClass(_A("A"), _A("AA"))); - REQUIRE_THAT(src, IsBaseClass(_A("AA"), _A("AAA"))); - - REQUIRE_THAT(src, !IsClass(_A("B"))); - - REQUIRE_THAT(src, !IsDependency(_A("R"), _A("A"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "AA")); - REQUIRE(IsClass(j, "AAA")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("AAA"))); - REQUIRE_THAT(src, IsBaseClass(_A("A"), _A("AA"))); - REQUIRE_THAT(src, IsBaseClass(_A("AA"), _A("AAA"))); - - REQUIRE_THAT(src, !IsClass(_A("B"))); - - REQUIRE_THAT(src, !IsDependency(_A("R"), _A("A"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "AA")); + REQUIRE(IsClass(src, "AAA")); + REQUIRE(IsBaseClass(src, "A", "AA")); + REQUIRE(IsBaseClass(src, "AA", "AAA")); + REQUIRE(!IsClass(src, "B")); + REQUIRE(!IsDependency(src, "R", "A")); + }); } \ No newline at end of file diff --git a/tests/t00041/test_case.h b/tests/t00041/test_case.h index 28fc90e3..2fbfd147 100644 --- a/tests/t00041/test_case.h +++ b/tests/t00041/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00041/test_case.cc + * tests/t00041/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,108 +16,43 @@ * limitations under the License. */ -TEST_CASE("t00041", "[test-case][class]") +TEST_CASE("t00041") { - auto [config, db] = load_config("t00041"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00041_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00041", "t00041_class"); - REQUIRE(diagram->name == "t00041_class"); REQUIRE(diagram->generate_packages() == false); - auto model = generate_class_diagram(*db, diagram); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!IsClass(src, "A")); + REQUIRE(!IsClass(src, "AA")); + REQUIRE(!IsClass(src, "AAA")); - REQUIRE(model->name() == "t00041_class"); + REQUIRE(!IsClass(src, "B")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClass(src, "E")); + REQUIRE(IsClass(src, "F")); + REQUIRE(IsClass(src, "R")); + REQUIRE(IsClass(src, "RR")); + REQUIRE(IsClass(src, "RRR")); + REQUIRE(!IsClass(src, "detail::G")); + REQUIRE(!IsClass(src, "H")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(IsBaseClass(src, "R", "RR")); + REQUIRE(IsBaseClass(src, "RR", "RRR")); - REQUIRE_THAT(src, !IsClass(_A("A"))); - REQUIRE_THAT(src, !IsClass(_A("AA"))); - REQUIRE_THAT(src, !IsClass(_A("AAA"))); + REQUIRE(IsAssociation(src, "D", "RR", "rr")); + REQUIRE(IsAssociation(src, "RR", "E", "e")); + REQUIRE(IsAssociation(src, "RR", "F", "f")); + REQUIRE(!IsDependency(src, "RR", "H")); - REQUIRE_THAT(src, !IsClass(_A("B"))); - - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - REQUIRE_THAT(src, IsClass(_A("RR"))); - REQUIRE_THAT(src, IsClass(_A("RRR"))); - REQUIRE_THAT(src, !IsClass(_A("detail::G"))); - REQUIRE_THAT(src, !IsClass(_A("H"))); - - REQUIRE_THAT(src, IsBaseClass(_A("R"), _A("RR"))); - REQUIRE_THAT(src, IsBaseClass(_A("RR"), _A("RRR"))); - - REQUIRE_THAT(src, IsAssociation(_A("D"), _A("RR"), "+rr")); - REQUIRE_THAT(src, IsAssociation(_A("RR"), _A("E"), "+e")); - REQUIRE_THAT(src, IsAssociation(_A("RR"), _A("F"), "+f")); - REQUIRE_THAT(src, !IsDependency(_A("RR"), _A("H"))); - - REQUIRE_THAT(src, IsClass(_A("ns1::N"))); - REQUIRE_THAT(src, IsClass(_A("ns1::NN"))); - REQUIRE_THAT(src, IsClass(_A("ns1::NM"))); - REQUIRE_THAT(src, IsBaseClass(_A("ns1::N"), _A("ns1::NN"))); - REQUIRE_THAT(src, IsBaseClass(_A("ns1::N"), _A("ns1::NM"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(!IsClass(j, "A")); - REQUIRE(!IsClass(j, "AA")); - REQUIRE(!IsClass(j, "AAA")); - REQUIRE(IsClass(j, "D")); - REQUIRE(IsClass(j, "E")); - REQUIRE(IsClass(j, "F")); - REQUIRE(IsClass(j, "R")); - - REQUIRE(IsAssociation(j, "D", "RR", "rr")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, !IsClass(_A("A"))); - REQUIRE_THAT(src, !IsClass(_A("AA"))); - REQUIRE_THAT(src, !IsClass(_A("AAA"))); - - REQUIRE_THAT(src, !IsClass(_A("B"))); - - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - REQUIRE_THAT(src, IsClass(_A("RR"))); - REQUIRE_THAT(src, IsClass(_A("RRR"))); - REQUIRE_THAT(src, !IsClass(_A("detail::G"))); - REQUIRE_THAT(src, !IsClass(_A("H"))); - - REQUIRE_THAT(src, IsBaseClass(_A("R"), _A("RR"))); - REQUIRE_THAT(src, IsBaseClass(_A("RR"), _A("RRR"))); - - REQUIRE_THAT(src, IsAssociation(_A("D"), _A("RR"), "+rr")); - REQUIRE_THAT(src, IsAssociation(_A("RR"), _A("E"), "+e")); - REQUIRE_THAT(src, IsAssociation(_A("RR"), _A("F"), "+f")); - REQUIRE_THAT(src, !IsDependency(_A("RR"), _A("H"))); - - REQUIRE_THAT(src, IsClass(_A("ns1::N"))); - REQUIRE_THAT(src, IsClass(_A("ns1::NN"))); - REQUIRE_THAT(src, IsClass(_A("ns1::NM"))); - REQUIRE_THAT(src, IsBaseClass(_A("ns1::N"), _A("ns1::NN"))); - REQUIRE_THAT(src, IsBaseClass(_A("ns1::N"), _A("ns1::NM"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsClass(src, {"ns1", "N"})); + REQUIRE(IsClass(src, {"ns1", "NN"})); + REQUIRE(IsClass(src, {"ns1", "NM"})); + REQUIRE(IsBaseClass(src, "ns1::N", "ns1::NN")); + REQUIRE(IsBaseClass(src, "ns1::N", "ns1::NM")); + }); } \ No newline at end of file diff --git a/tests/t00042/test_case.h b/tests/t00042/test_case.h index 795220eb..b5c411ea 100644 --- a/tests/t00042/test_case.h +++ b/tests/t00042/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00042/test_case.cc + * tests/t00042/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,51 +16,18 @@ * limitations under the License. */ -TEST_CASE("t00042", "[test-case][class]") +TEST_CASE("t00042") { - auto [config, db] = load_config("t00042"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00042_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00042", "t00042_class"); - REQUIRE(diagram->name == "t00042_class"); REQUIRE(diagram->generate_packages() == false); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00042_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClassTemplate("A", "T")); - REQUIRE_THAT(src, IsClassTemplate("B", "T,K")); - REQUIRE_THAT(src, !IsClassTemplate("C", "T")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClassTemplate(j, "A")); - REQUIRE(IsClassTemplate(j, "B")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("C"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "B")); + REQUIRE(!IsClassTemplate(src, "C")); + }); } \ No newline at end of file diff --git a/tests/t00043/test_case.h b/tests/t00043/test_case.h index abc539de..1f81bb68 100644 --- a/tests/t00043/test_case.h +++ b/tests/t00043/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00043/test_case.cc + * tests/t00043/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,117 +16,38 @@ * limitations under the License. */ -TEST_CASE("t00043", "[test-case][class]") +TEST_CASE("t00043") { - auto [config, db] = load_config("t00043"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00043_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00043", "t00043_class"); - REQUIRE(diagram->name == "t00043_class"); - REQUIRE(diagram->generate_packages() == true); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, {"dependants", "A"})); + REQUIRE(IsClass(src, {"dependants", "B"})); + REQUIRE(IsClass(src, {"dependants", "C"})); + REQUIRE(IsClass(src, {"dependants", "D"})); + REQUIRE(IsClass(src, {"dependants", "BB"})); + REQUIRE(IsClass(src, {"dependants", "E"})); + REQUIRE(IsDependency(src, {"dependants", "B"}, {"dependants", "A"})); + REQUIRE(IsDependency(src, {"dependants", "BB"}, {"dependants", "A"})); + REQUIRE(IsDependency(src, {"dependants", "C"}, {"dependants", "B"})); + REQUIRE(IsDependency(src, {"dependants", "D"}, {"dependants", "C"})); + REQUIRE(IsDependency(src, {"dependants", "E"}, {"dependants", "D"})); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClass(src, {"dependencies", "G"})); + REQUIRE(IsClass(src, {"dependencies", "GG"})); + REQUIRE(IsClass(src, {"dependencies", "H"})); + REQUIRE(!IsClass(src, {"dependencies", "HH"})); - REQUIRE(model->name() == "t00043_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check dependants filter - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("BB"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, !IsClass(_A("F"))); - - REQUIRE_THAT(src, IsDependency(_A("B"), _A("A"))); - REQUIRE_THAT(src, IsDependency(_A("BB"), _A("A"))); - REQUIRE_THAT(src, IsDependency(_A("C"), _A("B"))); - REQUIRE_THAT(src, IsDependency(_A("D"), _A("C"))); - REQUIRE_THAT(src, IsDependency(_A("E"), _A("D"))); - - // Check dependencies filter - REQUIRE_THAT(src, IsClass(_A("G"))); - REQUIRE_THAT(src, IsClass(_A("GG"))); - REQUIRE_THAT(src, IsClass(_A("H"))); - REQUIRE_THAT(src, !IsClass(_A("HH"))); - REQUIRE_THAT(src, IsClass(_A("I"))); - REQUIRE_THAT(src, IsClass(_A("J"))); - - REQUIRE_THAT(src, IsDependency(_A("H"), _A("G"))); - REQUIRE_THAT(src, IsDependency(_A("H"), _A("GG"))); - REQUIRE_THAT(src, IsDependency(_A("I"), _A("H"))); - REQUIRE_THAT(src, IsDependency(_A("J"), _A("I"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "dependants::A")); - REQUIRE(IsClass(j, "dependants::B")); - REQUIRE(IsClass(j, "dependants::C")); - REQUIRE(IsClass(j, "dependants::D")); - REQUIRE(IsClass(j, "dependants::BB")); - REQUIRE(IsClass(j, "dependants::E")); - REQUIRE(IsDependency(j, "dependants::B", "dependants::A")); - - REQUIRE(IsClass(j, "dependencies::G")); - REQUIRE(IsClass(j, "dependencies::GG")); - REQUIRE(IsClass(j, "dependencies::H")); - REQUIRE(IsDependency(j, "dependencies::J", "dependencies::I")); - REQUIRE(IsDependency(j, "dependencies::H", "dependencies::G")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - // Check dependants filter - REQUIRE_THAT(src, IsClass(_A("dependants::A"))); - REQUIRE_THAT(src, IsClass(_A("dependants::B"))); - REQUIRE_THAT(src, IsClass(_A("dependants::BB"))); - REQUIRE_THAT(src, IsClass(_A("dependants::D"))); - REQUIRE_THAT(src, IsClass(_A("dependants::E"))); - REQUIRE_THAT(src, !IsClass(_A("dependants::F"))); - - REQUIRE_THAT( - src, IsDependency(_A("dependants::B"), _A("dependants::A"))); - REQUIRE_THAT( - src, IsDependency(_A("dependants::BB"), _A("dependants::A"))); - REQUIRE_THAT( - src, IsDependency(_A("dependants::C"), _A("dependants::B"))); - REQUIRE_THAT( - src, IsDependency(_A("dependants::D"), _A("dependants::C"))); - REQUIRE_THAT( - src, IsDependency(_A("dependants::E"), _A("dependants::D"))); - - // Check dependencies filter - REQUIRE_THAT(src, IsClass(_A("dependencies::G"))); - REQUIRE_THAT(src, IsClass(_A("dependencies::GG"))); - REQUIRE_THAT(src, IsClass(_A("dependencies::H"))); - REQUIRE_THAT(src, !IsClass(_A("dependencies::HH"))); - REQUIRE_THAT(src, IsClass(_A("dependencies::I"))); - REQUIRE_THAT(src, IsClass(_A("dependencies::J"))); - - REQUIRE_THAT( - src, IsDependency(_A("dependencies::H"), _A("dependencies::G"))); - REQUIRE_THAT( - src, IsDependency(_A("dependencies::H"), _A("dependencies::GG"))); - REQUIRE_THAT( - src, IsDependency(_A("dependencies::I"), _A("dependencies::H"))); - REQUIRE_THAT( - src, IsDependency(_A("dependencies::J"), _A("dependencies::I"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE( + IsDependency(src, {"dependencies", "J"}, {"dependencies", "I"})); + REQUIRE( + IsDependency(src, {"dependencies", "H"}, {"dependencies", "G"})); + REQUIRE( + IsDependency(src, {"dependencies", "I"}, {"dependencies", "H"})); + REQUIRE( + IsDependency(src, {"dependencies", "H"}, {"dependencies", "GG"})); + }); } \ No newline at end of file diff --git a/tests/t00044/test_case.h b/tests/t00044/test_case.h index 3f04d11d..da66d8e7 100644 --- a/tests/t00044/test_case.h +++ b/tests/t00044/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00044/test_case.cc + * tests/t00044/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,103 +16,35 @@ * limitations under the License. */ -TEST_CASE("t00044", "[test-case][class]") +TEST_CASE("t00044") { - auto [config, db] = load_config("t00044"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00044_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00044", "t00044_class"); - REQUIRE(diagram->name == "t00044_class"); - REQUIRE(diagram->generate_packages() == true); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!src.contains("type-parameter-")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClassTemplate(src, "sink")); + REQUIRE(IsClassTemplate(src, "signal_handler")); - REQUIRE(model->name() == "t00044_class"); + REQUIRE(IsClassTemplate(src, "signal_handler")); + REQUIRE(IsClassTemplate(src, "signal_handler")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsClassTemplate(src, "sink>")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(IsInstantiation( + src, "sink", "sink>")); - REQUIRE_THAT(src, !Contains("type-parameter-")); + REQUIRE(IsInstantiation(src, "sink>", + "sink>")); - REQUIRE_THAT(src, IsClassTemplate("sink", "T")); - REQUIRE_THAT(src, IsClassTemplate("signal_handler", "T,A")); + REQUIRE(IsClassTemplate(src, "signal_handler")); + REQUIRE(IsInstantiation( + src, "signal_handler", "signal_handler")); - REQUIRE_THAT(src, IsClassTemplate("signal_handler", "Ret(Args...),A")); - REQUIRE_THAT(src, IsClassTemplate("signal_handler", "void(int),bool")); - - REQUIRE_THAT( - src, IsClassTemplate("sink", "signal_handler")); - - REQUIRE_THAT(src, - IsInstantiation( - _A("sink"), _A("sink>"))); - - REQUIRE_THAT(src, - IsInstantiation(_A("sink>"), - _A("sink>"))); - - REQUIRE_THAT(src, IsClassTemplate("signal_handler", "T,A")); - REQUIRE_THAT(src, - IsInstantiation(_A("signal_handler"), - _A("signal_handler"))); - - REQUIRE_THAT(src, - IsInstantiation(_A("signal_handler"), - _A("signal_handler"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClassTemplate(j, "sink")); - REQUIRE(IsClassTemplate(j, "signal_handler")); - REQUIRE(IsClassTemplate(j, "signal_handler")); - REQUIRE(IsStruct(j, "signal_handler")); - REQUIRE(IsClassTemplate(j, "signal_handler")); - REQUIRE(IsClassTemplate(j, "sink>")); - REQUIRE(IsStruct(j, "R")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, !Contains("type-parameter-")); - - REQUIRE_THAT(src, IsClass(_A("sink"))); - REQUIRE_THAT(src, IsClass(_A("signal_handler"))); - - REQUIRE_THAT(src, IsClass(_A("signal_handler"))); - REQUIRE_THAT(src, IsClass(_A("signal_handler"))); - - REQUIRE_THAT(src, IsClass(_A("sink>"))); - - REQUIRE_THAT(src, - IsInstantiation( - _A("sink"), _A("sink>"))); - - REQUIRE_THAT(src, - IsInstantiation(_A("sink>"), - _A("sink>"))); - - REQUIRE_THAT(src, IsClass(_A("signal_handler"))); - REQUIRE_THAT(src, - IsInstantiation(_A("signal_handler"), - _A("signal_handler"))); - - REQUIRE_THAT(src, - IsInstantiation(_A("signal_handler"), - _A("signal_handler"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsInstantiation(src, "signal_handler", + "signal_handler")); + }); } \ No newline at end of file diff --git a/tests/t00045/test_case.h b/tests/t00045/test_case.h index 604308b4..be6b8957 100644 --- a/tests/t00045/test_case.h +++ b/tests/t00045/test_case.h @@ -16,109 +16,40 @@ * limitations under the License. */ -TEST_CASE("t00045", "[test-case][class]") +TEST_CASE("t00045") { - auto [config, db] = load_config("t00045"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00045_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00045", "t00045_class"); - REQUIRE(diagram->name == "t00045_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, {"ns1", "A"})); + REQUIRE(IsClass(src, {"ns1::ns2", "A"})); + REQUIRE(IsClass(src, {"ns1::ns2", "B"})); + REQUIRE(IsClass(src, {"ns1::ns2", "C"})); + REQUIRE(IsClass(src, {"ns1::ns2", "D"})); + REQUIRE(IsClass(src, {"ns1::ns2", "E"})); + REQUIRE(IsClass(src, {"ns1::ns2", "R"})); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsBaseClass(src, {"ns1::ns2", "A"}, {"ns1::ns2", "B"})); + REQUIRE(IsBaseClass(src, {"ns1", "A"}, {"ns1::ns2", "C"})); + REQUIRE(IsBaseClass(src, {"ns1::ns2", "A"}, {"ns1::ns2", "D"})); + REQUIRE(IsBaseClass(src, "A", {"ns1::ns2", "E"})); - REQUIRE(model->name() == "t00045_class"); + REQUIRE(IsAssociation(src, "ns1::ns2::R", "ns1::ns2::A", "a")); + REQUIRE(IsAssociation(src, "ns1::ns2::R", "ns1::A", "ns1_a")); + REQUIRE(IsAssociation( + src, "ns1::ns2::R", "ns1::ns2::A", "ns1_ns2_a")); + REQUIRE(IsAssociation(src, "ns1::ns2::R", "A", "root_a")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsDependency(src, "ns1::ns2::R", "AA")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::B"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::C"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::D"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::E"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::R"))); - - REQUIRE_THAT(src, IsBaseClass(_A("ns1::ns2::A"), _A("ns1::ns2::B"))); - REQUIRE_THAT(src, IsBaseClass(_A("ns1::A"), _A("ns1::ns2::C"))); - REQUIRE_THAT(src, IsBaseClass(_A("ns1::ns2::A"), _A("ns1::ns2::D"))); - REQUIRE_THAT(src, IsBaseClass(_A("A"), _A("ns1::ns2::E"))); - - REQUIRE_THAT( - src, IsAssociation(_A("ns1::ns2::R"), _A("ns1::ns2::A"), "+a")); - REQUIRE_THAT( - src, IsAssociation(_A("ns1::ns2::R"), _A("ns1::A"), "+ns1_a")); - REQUIRE_THAT(src, - IsAssociation(_A("ns1::ns2::R"), _A("ns1::ns2::A"), "+ns1_ns2_a")); - REQUIRE_THAT(src, IsAssociation(_A("ns1::ns2::R"), _A("A"), "+root_a")); - - REQUIRE_THAT(src, IsDependency(_A("ns1::ns2::R"), _A("AA"))); - - REQUIRE_THAT(src, IsFriend(_A("ns1::ns2::R"), _A("AAA"))); - REQUIRE_THAT( - src, !IsFriend(_A("ns1::ns2::R"), _A("ns1::ns2::AAA"))); + REQUIRE(IsFriend(src, "ns1::ns2::R", "AAA")); + REQUIRE(!IsFriend(src, "ns1::ns2::R", "ns1::ns2::AAA")); // TODO: - // REQUIRE_THAT(puml, IsFriend(_A("ns1::ns2::R"), + // REQUIRE(puml, IsFriend(src, "ns1::ns2::R"), // _A("AAAA"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "ns1::A")); - REQUIRE(IsClass(j, "ns1::ns2::A")); - REQUIRE(IsClass(j, "ns1::ns2::B")); - REQUIRE(IsClass(j, "ns1::ns2::C")); - REQUIRE(IsClass(j, "ns1::ns2::D")); - REQUIRE(IsClass(j, "ns1::ns2::E")); - REQUIRE(IsClass(j, "ns1::ns2::R")); - - REQUIRE(IsBaseClass(j, "ns1::ns2::A", "ns1::ns2::B")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsFriend; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::B"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::C"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::D"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::E"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::R"))); - - REQUIRE_THAT(src, IsBaseClass(_A("ns1::ns2::A"), _A("ns1::ns2::B"))); - REQUIRE_THAT(src, IsBaseClass(_A("ns1::A"), _A("ns1::ns2::C"))); - REQUIRE_THAT(src, IsBaseClass(_A("ns1::ns2::A"), _A("ns1::ns2::D"))); - REQUIRE_THAT(src, IsBaseClass(_A("A"), _A("ns1::ns2::E"))); - - REQUIRE_THAT( - src, IsAssociation(_A("ns1::ns2::R"), _A("ns1::ns2::A"), "+a")); - REQUIRE_THAT( - src, IsAssociation(_A("ns1::ns2::R"), _A("ns1::A"), "+ns1_a")); - REQUIRE_THAT(src, - IsAssociation(_A("ns1::ns2::R"), _A("ns1::ns2::A"), "+ns1_ns2_a")); - REQUIRE_THAT(src, IsAssociation(_A("ns1::ns2::R"), _A("A"), "+root_a")); - - REQUIRE_THAT(src, IsDependency(_A("ns1::ns2::R"), _A("AA"))); - - REQUIRE_THAT(src, IsFriend(_A("ns1::ns2::R"), _A("AAA"))); - REQUIRE_THAT( - src, !IsFriend(_A("ns1::ns2::R"), _A("ns1::ns2::AAA"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + }); } \ No newline at end of file diff --git a/tests/t00046/test_case.h b/tests/t00046/test_case.h index 1352f8b5..b7fca9a4 100644 --- a/tests/t00046/test_case.h +++ b/tests/t00046/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00046/test_case.cc + * tests/t00046/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,63 +16,23 @@ * limitations under the License. */ -TEST_CASE("t00046", "[test-case][class]") +TEST_CASE("t00046") { - auto [config, db] = load_config("t00046"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00046_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00046", "t00046_class"); - REQUIRE(diagram->name == "t00046_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "AA")); + REQUIRE(IsClass(src, {"ns1::ns2", "B"})); + REQUIRE(IsClass(src, {"ns1::ns2", "C"})); + REQUIRE(IsClass(src, {"ns1::ns2", "D"})); + REQUIRE(IsClass(src, {"ns1::ns2", "E"})); + REQUIRE(IsClass(src, {"ns1::ns2", "R"})); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00046_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsField("i", "std::vector")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(get_element(j, "A").value()["type"] == "class"); - REQUIRE(get_element(j, "AA").value()["type"] == "class"); - REQUIRE(get_element(j, "ns1::A").value()["type"] == "class"); - REQUIRE(get_element(j, "ns1::ns2::D").value()["type"] == "class"); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsField; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::B"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::C"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::D"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::E"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::R"))); - - REQUIRE_THAT(src, IsField("i", "std::vector")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsField( + src, {"ns1::ns2", "R"}, "i", "std::vector")); + }); } \ No newline at end of file diff --git a/tests/t00047/test_case.h b/tests/t00047/test_case.h index 19854832..bef97c84 100644 --- a/tests/t00047/test_case.h +++ b/tests/t00047/test_case.h @@ -16,60 +16,17 @@ * limitations under the License. */ -TEST_CASE("t00047", "[test-case][class]") +TEST_CASE("t00047") { - auto [config, db] = load_config("t00047"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00047_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00047", "t00047_class"); - REQUIRE(diagram->name == "t00047_class"); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00047_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if class templates exist - REQUIRE_THAT(src, IsClassTemplate("conditional_t", "Ts...")); - REQUIRE_THAT(src, IsClassTemplate("conditional_t", "Else")); - REQUIRE_THAT(src, - IsClassTemplate("conditional_t", "std::true_type,Result,Tail...")); - REQUIRE_THAT(src, - IsClassTemplate("conditional_t", "std::false_type,Result,Tail...")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClassTemplate(j, "conditional_t")); - REQUIRE(IsClass(j, "conditional_t")); - REQUIRE(IsClass(j, "conditional_t")); - REQUIRE(IsClass(j, "conditional_t")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - // Check if class templates exist - REQUIRE_THAT(src, IsClass(_A("conditional_t"))); - REQUIRE_THAT(src, IsClass(_A("conditional_t"))); - REQUIRE_THAT( - src, IsClass(_A("conditional_t"))); - REQUIRE_THAT( - src, IsClass(_A("conditional_t"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClassTemplate(src, "conditional_t")); + REQUIRE(IsClass(src, "conditional_t")); + REQUIRE(IsClass(src, "conditional_t")); + REQUIRE(IsClass(src, "conditional_t")); + }); } \ No newline at end of file diff --git a/tests/t00048/test_case.h b/tests/t00048/test_case.h index 38ecc80b..f7f7b5f3 100644 --- a/tests/t00048/test_case.h +++ b/tests/t00048/test_case.h @@ -16,75 +16,26 @@ * limitations under the License. */ -TEST_CASE("t00048", "[test-case][class]") +TEST_CASE("t00048") { - auto [config, db] = load_config("t00048"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00048_class"]; - - REQUIRE(diagram->name == "t00048_class"); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00048_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00048", "t00048_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { // Check if all classes exist - REQUIRE_THAT(src, IsAbstractClass(_A("Base"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); + REQUIRE(IsAbstractClass(src, "Base")); + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); // Check if class templates exist - REQUIRE_THAT(src, IsAbstractClassTemplate("BaseTemplate", "T")); - REQUIRE_THAT(src, IsClassTemplate("ATemplate", "T")); - REQUIRE_THAT(src, IsClassTemplate("BTemplate", "T")); + REQUIRE(IsAbstractClassTemplate(src, "BaseTemplate")); + REQUIRE(IsClassTemplate(src, "ATemplate")); + REQUIRE(IsClassTemplate(src, "BTemplate")); // Check if all inheritance relationships exist - REQUIRE_THAT(src, IsBaseClass(_A("Base"), _A("A"))); - REQUIRE_THAT(src, IsBaseClass(_A("Base"), _A("B"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "ATemplate")); - REQUIRE(IsClass(j, "BTemplate")); - REQUIRE(IsBaseClass(j, "Base", "A")); - REQUIRE(IsBaseClass(j, "Base", "B")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsAbstractClass; - - // Check if all classes exist - REQUIRE_THAT(src, IsAbstractClass(_A("Base"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - - // Check if class templates exist - REQUIRE_THAT(src, IsAbstractClass(_A("BaseTemplate"))); - REQUIRE_THAT(src, IsClass(_A("ATemplate"))); - REQUIRE_THAT(src, IsClass(_A("BTemplate"))); - - // Check if all inheritance relationships exist - REQUIRE_THAT(src, IsBaseClass(_A("Base"), _A("A"))); - REQUIRE_THAT(src, IsBaseClass(_A("Base"), _A("B"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsBaseClass(src, "Base", "A")); + REQUIRE(IsBaseClass(src, "Base", "B")); + }); } \ No newline at end of file diff --git a/tests/t00049/test_case.h b/tests/t00049/test_case.h index 01494fc3..b75afa8f 100644 --- a/tests/t00049/test_case.h +++ b/tests/t00049/test_case.h @@ -16,89 +16,29 @@ * limitations under the License. */ -TEST_CASE("t00049", "[test-case][class]") +TEST_CASE("t00049") { - auto [config, db] = load_config("t00049"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00049_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00049", "t00049_class"); - REQUIRE(diagram->name == "t00049_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "R")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClassTemplate(src, "A")); - REQUIRE(model->name() == "t00049_class"); + REQUIRE(IsMethod(src, "R", "get_int_map", "A")); + REQUIRE(IsMethod( + src, "R", "set_int_map", "void", "A && int_map")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsField(src, "R", "a_string", "A")); + REQUIRE( + IsField(src, "R", "a_vector_string", "A")); + REQUIRE(IsField(src, "R", "a_int_map", "A")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("R"))); - - // Check if class templates exist - REQUIRE_THAT(src, IsClassTemplate("A", "T")); - - // Check if all methods exist - REQUIRE_THAT(src, (IsMethod("get_int_map", "A"))); - REQUIRE_THAT(src, - (IsMethod("set_int_map", "void", "A && int_map"))); - - // Check if all fields exist - REQUIRE_THAT(src, (IsField("a_string", "A"))); - REQUIRE_THAT( - src, (IsField("a_vector_string", "A"))); - REQUIRE_THAT(src, (IsField("a_int_map", "A"))); - - // Check if all relationships exist - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "R")); - REQUIRE(IsClassTemplate(j, "A")); - REQUIRE(IsInstantiation(j, "A", "A")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsField; - using mermaid::IsMethod; - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("R"))); - - // Check if class templates exist - REQUIRE_THAT(src, IsClass(_A("A"))); - - // Check if all methods exist - REQUIRE_THAT(src, (IsMethod("get_int_map", "A"))); - REQUIRE_THAT(src, - (IsMethod("set_int_map", "void", "A && int_map"))); - - // Check if all fields exist - REQUIRE_THAT(src, (IsField("a_string", "A"))); - REQUIRE_THAT( - src, (IsField("a_vector_string", "A"))); - REQUIRE_THAT(src, (IsField("a_int_map", "A"))); - - // Check if all relationships exist - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); + }); } \ No newline at end of file diff --git a/tests/t00050/test_case.h b/tests/t00050/test_case.h index 6a3c50dd..32802240 100644 --- a/tests/t00050/test_case.h +++ b/tests/t00050/test_case.h @@ -16,85 +16,38 @@ * limitations under the License. */ -TEST_CASE("t00050", "[test-case][class]") +TEST_CASE("t00050") { - auto [config, db] = load_config("t00050"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00050_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00050", "t00050_class"); - REQUIRE(diagram->name == "t00050_class"); + CHECK_CLASS_DIAGRAM( + config, diagram, *model, + [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, {"utils", "D"})); + REQUIRE(IsEnum(src, "E")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00050_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("utils::D"))); - REQUIRE_THAT(src, IsEnum(_A("E"))); - - REQUIRE_THAT(src, HasNote(_A("A"), "left")); - REQUIRE_THAT(src, HasNote(_A("A"), "right")); - REQUIRE_THAT(src, HasNote(_A("B"), "top")); - REQUIRE_THAT(src, HasNote(_A("C"), "top")); - REQUIRE_THAT(src, HasNote(_A("utils::D"), "top")); - REQUIRE_THAT(src, !HasNote(_A("E"), "bottom")); - REQUIRE_THAT(src, !HasNote(_A("NoComment"), "top")); - REQUIRE_THAT(src, HasNote(_A("F"), "top")); - REQUIRE_THAT(src, HasNote(_A("G"), "top")); - REQUIRE_THAT(src, HasNote(_A("G"), "bottom")); - REQUIRE_THAT(src, HasNote(_A("G"), "right")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsClass(j, "utils::D")); - REQUIRE(IsEnum(j, "E")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::HasNote; - using mermaid::IsEnum; - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("utils::D"))); - REQUIRE_THAT(src, IsEnum(_A("E"))); - - REQUIRE_THAT(src, HasNote(_A("A"), "left")); - REQUIRE_THAT(src, HasNote(_A("A"), "right")); - REQUIRE_THAT(src, HasNote(_A("B"), "top")); - REQUIRE_THAT(src, HasNote(_A("C"), "top")); - REQUIRE_THAT(src, HasNote(_A("utils::D"), "top")); - REQUIRE_THAT(src, !HasNote(_A("E"), "bottom")); - REQUIRE_THAT(src, !HasNote(_A("NoComment"), "top")); - REQUIRE_THAT(src, HasNote(_A("F"), "top")); - REQUIRE_THAT(src, HasNote(_A("G"), "top")); - REQUIRE_THAT(src, HasNote(_A("G"), "bottom")); - REQUIRE_THAT(src, HasNote(_A("G"), "right")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(HasNote(src, "A", "left")); + REQUIRE(HasNote(src, "A", "right")); + REQUIRE(HasNote(src, "B", "top")); + REQUIRE(HasNote(src, "C", "top")); + REQUIRE(HasNote(src, "utils::D", "top")); + REQUIRE(HasNote(src, "F", "top")); + REQUIRE(HasNote(src, "G", "top")); + REQUIRE(HasNote(src, "G", "bottom")); + REQUIRE(HasNote(src, "G", "right")); + }, + [](const plantuml_t &src) { + REQUIRE(!HasNote(src, "E", "bottom")); + REQUIRE(!HasNote(src, "NoComment", "top")); + }, + [](const mermaid_t &src) { + REQUIRE(!HasNote(src, "E", "bottom")); + REQUIRE(!HasNote(src, "NoComment", "top")); + }); } \ No newline at end of file diff --git a/tests/t00051/test_case.h b/tests/t00051/test_case.h index c2302184..f3f3c39a 100644 --- a/tests/t00051/test_case.h +++ b/tests/t00051/test_case.h @@ -16,116 +16,40 @@ * limitations under the License. */ -TEST_CASE("t00051", "[test-case][class]") +TEST_CASE("t00051") { - auto [config, db] = load_config("t00051"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00051_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00051", "t00051_class"); - REQUIRE(diagram->name == "t00051_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsInnerClass(src, "A", "A::custom_thread1")); + REQUIRE(IsInnerClass(src, "A", "A::custom_thread2")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsMethod(src, "A::custom_thread1", + "custom_thread1", "void", + "Function && f, Args &&... args")); + REQUIRE(IsMethod(src, "A::custom_thread2", "thread", "void", + "(lambda at t00051.cc:59:27) &&")); + REQUIRE(IsMethod(src, "A", "start_thread3", + "B<(lambda at t00051.cc:43:18),(lambda at " + "t00051.cc:43:27)>")); + REQUIRE(IsMethod( + src, "A", "get_function", "(lambda at t00051.cc:48:16)")); - REQUIRE(model->name() == "t00051_class"); + REQUIRE(IsClassTemplate(src, "B")); + REQUIRE(IsMethod(src, "B", "f", "void")); + REQUIRE(IsMethod(src, "B", "ff", "void")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsClassTemplate( + src, "B<(lambda at t00051.cc:43:18),(lambda at t00051.cc:43:27)>")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(IsInstantiation(src, "B", + "B<(lambda at t00051.cc:43:18),(lambda at t00051.cc:43:27)>")); - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsInnerClass(_A("A"), _A("A::custom_thread1"))); - REQUIRE_THAT(src, IsInnerClass(_A("A"), _A("A::custom_thread2"))); - - REQUIRE_THAT(src, - (IsMethod("custom_thread1", "void", - "Function && f, Args &&... args"))); - REQUIRE_THAT(src, - (IsMethod( - "thread", "void", "(lambda at t00051.cc:59:27) &&"))); - REQUIRE_THAT(src, - (IsMethod("start_thread3", - "B<(lambda at t00051.cc:43:18),(lambda at " - "t00051.cc:43:27)>"))); - REQUIRE_THAT(src, - (IsMethod("get_function", "(lambda at t00051.cc:48:16)"))); - - REQUIRE_THAT(src, IsClassTemplate("B", "F,FF=F")); - REQUIRE_THAT(src, (IsMethod("f", "void"))); - REQUIRE_THAT(src, (IsMethod("ff", "void"))); - - REQUIRE_THAT(src, - IsClassTemplate("B", - "(lambda at t00051.cc:43:18),(lambda at t00051.cc:43:27)")); - - REQUIRE_THAT(src, - IsInstantiation(_A("B"), - _A("B<(lambda at t00051.cc:43:18),(lambda at " - "t00051.cc:43:27)>"))); - - REQUIRE_THAT(src, - IsDependency(_A("A"), - _A("B<(lambda at t00051.cc:43:18),(lambda " - "at t00051.cc:43:27)>"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsInnerClass(j, "A", "A::custom_thread1")); - REQUIRE(IsInnerClass(j, "A", "A::custom_thread2")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsInnerClass; - using mermaid::IsMethod; - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsInnerClass(_A("A"), _A("A::custom_thread1"))); - REQUIRE_THAT(src, IsInnerClass(_A("A"), _A("A::custom_thread2"))); - - REQUIRE_THAT(src, - (IsMethod("custom_thread1", "void", - "Function && f, Args &&... args"))); - REQUIRE_THAT(src, - (IsMethod( - "thread", "void", "(lambda at t00051.cc:59:27) &&"))); - REQUIRE_THAT(src, - (IsMethod("start_thread3", - "B<(lambda at t00051.cc:43:18),(lambda at t00051.cc:43:27)>"))); - REQUIRE_THAT(src, - (IsMethod("get_function", "(lambda at t00051.cc:48:16)"))); - - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, (IsMethod("f", "void"))); - REQUIRE_THAT(src, (IsMethod("ff", "void"))); - - REQUIRE_THAT(src, - IsClass(_A("B<(lambda at t00051.cc:43:18),(lambda at " - "t00051.cc:43:27)>"))); - - REQUIRE_THAT(src, - IsInstantiation(_A("B"), - _A("B<(lambda at t00051.cc:43:18),(lambda at " - "t00051.cc:43:27)>"))); - - REQUIRE_THAT(src, - IsDependency(_A("A"), - _A("B<(lambda at t00051.cc:43:18),(lambda " - "at t00051.cc:43:27)>"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "A", + "B<(lambda at t00051.cc:43:18),(lambda at t00051.cc:43:27)>")); + }); } \ No newline at end of file diff --git a/tests/t00052/test_case.h b/tests/t00052/test_case.h index 32319443..e9c27346 100644 --- a/tests/t00052/test_case.h +++ b/tests/t00052/test_case.h @@ -16,67 +16,21 @@ * limitations under the License. */ -TEST_CASE("t00052", "[test-case][class]") +TEST_CASE("t00052") { - auto [config, db] = load_config("t00052"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00052_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00052", "t00052_class"); - REQUIRE(diagram->name == "t00052_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClassTemplate(src, "B")); - REQUIRE(model->name() == "t00052_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - - // Check if class templates exist - REQUIRE_THAT(src, IsClassTemplate("B", "T")); - - // Check if all methods exist - REQUIRE_THAT(src, (IsMethod("a", "T", "T p"))); - REQUIRE_THAT(src, (IsMethod("aa", "void", "F && f, Q q"))); - REQUIRE_THAT(src, (IsMethod("b", "T", "T t"))); - REQUIRE_THAT(src, (IsMethod("bb", "T", "F && f, T t"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClassTemplate(j, "B")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsMethod; - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - - // Check if class templates exist - REQUIRE_THAT(src, IsClass(_A("B"))); - - // Check if all methods exist - REQUIRE_THAT(src, (IsMethod("a", "T", "T p"))); - REQUIRE_THAT(src, (IsMethod("aa", "void", "F && f, Q q"))); - REQUIRE_THAT(src, (IsMethod("b", "T", "T t"))); - REQUIRE_THAT(src, (IsMethod("bb", "T", "F && f, T t"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsMethod(src, "A", "a", "T", "T p")); + REQUIRE(IsMethod(src, "A", "aa", "void", "F && f, Q q")); + REQUIRE(IsMethod(src, "B", "b", "T", "T t")); + REQUIRE(IsMethod(src, "B", "bb", "T", "F && f, T t")); + }); } \ No newline at end of file diff --git a/tests/t00053/test_case.h b/tests/t00053/test_case.h index 5cd14eb6..23d3b4ac 100644 --- a/tests/t00053/test_case.h +++ b/tests/t00053/test_case.h @@ -16,90 +16,28 @@ * limitations under the License. */ -TEST_CASE("t00053", "[test-case][class]") +TEST_CASE("t00053") { - auto [config, db] = load_config("t00053"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00053_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00053", "t00053_class"); - REQUIRE(diagram->name == "t00053_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "a")); + REQUIRE(IsClass(src, "b")); + REQUIRE(IsClass(src, "c")); + REQUIRE(IsClass(src, "d")); + REQUIRE(IsClass(src, "e")); + REQUIRE(IsClass(src, "f")); + REQUIRE(IsClass(src, "g")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00053_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("a"))); - REQUIRE_THAT(src, IsClass(_A("b"))); - REQUIRE_THAT(src, IsClass(_A("c"))); - REQUIRE_THAT(src, IsClass(_A("d"))); - REQUIRE_THAT(src, IsClass(_A("e"))); - REQUIRE_THAT(src, IsClass(_A("f"))); - REQUIRE_THAT(src, IsClass(_A("g"))); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "a")); - REQUIRE(IsClass(j, "b")); - REQUIRE(IsClass(j, "c")); - REQUIRE(IsClass(j, "d")); - REQUIRE(IsClass(j, "e")); - REQUIRE(IsClass(j, "f")); - REQUIRE(IsClass(j, "g")); - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsClass(j, "D")); - REQUIRE(IsClass(j, "E")); - REQUIRE(IsClass(j, "F")); - REQUIRE(IsClass(j, "G")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("a"))); - REQUIRE_THAT(src, IsClass(_A("b"))); - REQUIRE_THAT(src, IsClass(_A("c"))); - REQUIRE_THAT(src, IsClass(_A("d"))); - REQUIRE_THAT(src, IsClass(_A("e"))); - REQUIRE_THAT(src, IsClass(_A("f"))); - REQUIRE_THAT(src, IsClass(_A("g"))); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClass(src, "E")); + REQUIRE(IsClass(src, "F")); + REQUIRE(IsClass(src, "G")); + }); } \ No newline at end of file diff --git a/tests/t00054/test_case.h b/tests/t00054/test_case.h index 7fcf352a..43ff755b 100644 --- a/tests/t00054/test_case.h +++ b/tests/t00054/test_case.h @@ -16,103 +16,32 @@ * limitations under the License. */ -TEST_CASE("t00054", "[test-case][class]") +TEST_CASE("t00054") { - auto [config, db] = load_config("t00054"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00054_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00054", "t00054_class"); - REQUIRE(diagram->name == "t00054_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "a")); + REQUIRE(IsClass(src, "b")); + REQUIRE(IsClass(src, {"detail", "c"})); + REQUIRE(IsClass(src, {"detail", "d"})); + REQUIRE(IsClass(src, {"detail", "e"})); + REQUIRE(IsClass(src, "f")); + REQUIRE(IsClass(src, "g")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, {"detail2", "C"})); + REQUIRE(IsClass(src, {"detail2::detail3", "D"})); + REQUIRE(IsClass(src, {"detail2::detail3", "E"})); + REQUIRE(IsClass(src, {"detail2", "F"})); + REQUIRE(IsClass(src, "G")); - REQUIRE(model->name() == "t00054_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("a"))); - REQUIRE_THAT(src, IsClass(_A("b"))); - REQUIRE_THAT(src, IsClass(_A("c"))); - REQUIRE_THAT(src, IsClass(_A("d"))); - REQUIRE_THAT(src, IsClass(_A("e"))); - REQUIRE_THAT(src, IsClass(_A("f"))); - REQUIRE_THAT(src, IsClass(_A("g"))); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - - REQUIRE_THAT(src, IsEnum(_A("i"))); - REQUIRE_THAT(src, IsEnum(_A("h"))); - REQUIRE_THAT(src, IsEnum(_A("j"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "a")); - REQUIRE(IsClass(j, "b")); - REQUIRE(IsClass(j, "detail::c")); - REQUIRE(IsClass(j, "detail::d")); - REQUIRE(IsClass(j, "detail::e")); - REQUIRE(IsClass(j, "f")); - REQUIRE(IsClass(j, "g")); - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "detail2::C")); - REQUIRE(IsClass(j, "detail2::detail3::D")); - REQUIRE(IsClass(j, "detail2::detail3::E")); - REQUIRE(IsClass(j, "detail2::F")); - REQUIRE(IsClass(j, "G")); - - REQUIRE(IsEnum(j, "detail4::i")); - REQUIRE(IsEnum(j, "detail4::h")); - REQUIRE(IsEnum(j, "detail4::j")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsEnum; - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("a"))); - REQUIRE_THAT(src, IsClass(_A("b"))); - REQUIRE_THAT(src, IsClass(_A("detail::c"))); - REQUIRE_THAT(src, IsClass(_A("detail::d"))); - REQUIRE_THAT(src, IsClass(_A("detail::e"))); - REQUIRE_THAT(src, IsClass(_A("f"))); - REQUIRE_THAT(src, IsClass(_A("g"))); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("detail2::C"))); - REQUIRE_THAT(src, IsClass(_A("detail2::detail3::D"))); - REQUIRE_THAT(src, IsClass(_A("detail2::detail3::E"))); - REQUIRE_THAT(src, IsClass(_A("detail2::F"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - - REQUIRE_THAT(src, IsEnum(_A("detail4::i"))); - REQUIRE_THAT(src, IsEnum(_A("detail4::h"))); - REQUIRE_THAT(src, IsEnum(_A("detail4::j"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsEnum(src, {"detail4", "i"})); + REQUIRE(IsEnum(src, {"detail4", "h"})); + REQUIRE(IsEnum(src, {"detail4", "j"})); + }); } \ No newline at end of file diff --git a/tests/t00055/test_case.h b/tests/t00055/test_case.h index f349d5bf..25afa8d0 100644 --- a/tests/t00055/test_case.h +++ b/tests/t00055/test_case.h @@ -16,85 +16,33 @@ * limitations under the License. */ -TEST_CASE("t00055", "[test-case][class]") +TEST_CASE("t00055") { - auto [config, db] = load_config("t00055"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00055_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00055", "t00055_class"); - REQUIRE(diagram->name == "t00055_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClass(src, "E")); + REQUIRE(IsClass(src, "F")); + REQUIRE(IsClass(src, "G")); + REQUIRE(IsClass(src, "H")); + REQUIRE(IsClass(src, "I")); + REQUIRE(IsClass(src, "J")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsLayoutHint(src, "A", "right", "C")); + REQUIRE(IsLayoutHint(src, "C", "right", "E")); + REQUIRE(IsLayoutHint(src, "E", "right", "G")); + REQUIRE(IsLayoutHint(src, "G", "right", "I")); - REQUIRE(model->name() == "t00055_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - REQUIRE_THAT(src, IsClass(_A("H"))); - REQUIRE_THAT(src, IsClass(_A("I"))); - REQUIRE_THAT(src, IsClass(_A("J"))); - - REQUIRE_THAT(src, IsLayoutHint(_A("A"), "right", _A("C"))); - REQUIRE_THAT(src, IsLayoutHint(_A("C"), "right", _A("E"))); - REQUIRE_THAT(src, IsLayoutHint(_A("E"), "right", _A("G"))); - REQUIRE_THAT(src, IsLayoutHint(_A("G"), "right", _A("I"))); - - REQUIRE_THAT(src, IsLayoutHint(_A("B"), "down", _A("D"))); - REQUIRE_THAT(src, IsLayoutHint(_A("D"), "down", _A("F"))); - REQUIRE_THAT(src, IsLayoutHint(_A("F"), "down", _A("H"))); - REQUIRE_THAT(src, IsLayoutHint(_A("H"), "down", _A("J"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsClass(j, "D")); - REQUIRE(IsClass(j, "E")); - REQUIRE(IsClass(j, "F")); - REQUIRE(IsClass(j, "G")); - REQUIRE(IsClass(j, "H")); - REQUIRE(IsClass(j, "I")); - REQUIRE(IsClass(j, "J")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - REQUIRE_THAT(src, IsClass(_A("H"))); - REQUIRE_THAT(src, IsClass(_A("I"))); - REQUIRE_THAT(src, IsClass(_A("J"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsLayoutHint(src, "B", "down", "D")); + REQUIRE(IsLayoutHint(src, "D", "down", "F")); + REQUIRE(IsLayoutHint(src, "F", "down", "H")); + REQUIRE(IsLayoutHint(src, "H", "down", "J")); + }); } \ No newline at end of file diff --git a/tests/t00056/test_case.h b/tests/t00056/test_case.h index 8d6efee1..a74fcd43 100644 --- a/tests/t00056/test_case.h +++ b/tests/t00056/test_case.h @@ -16,212 +16,75 @@ * limitations under the License. */ -TEST_CASE("t00056", "[test-case][class]") +TEST_CASE("t00056") { - auto [config, db] = load_config("t00056"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00056_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00056", "t00056_class"); - REQUIRE(diagram->name == "t00056_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsConcept(src, "greater_than_simple")); + REQUIRE(IsConcept(src, "greater_than_with_requires")); + REQUIRE(IsConcept(src, "max_four_bytes")); + REQUIRE(IsConcept(src, "iterable")); + REQUIRE(IsConcept(src, "has_value_type")); + REQUIRE(IsConcept(src, "convertible_to_string")); + REQUIRE(IsConcept(src, "iterable_with_value_type")); + REQUIRE(IsConcept(src, "iterable_or_small_value_type")); + REQUIRE(IsConceptParameterList( + src, "greater_than_with_requires", "(T l,P r)")); + REQUIRE(IsConceptRequirement( + src, "greater_than_with_requires", "sizeof (l) > sizeof (r)")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00056_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsConcept(_A("greater_than_simple"))); - REQUIRE_THAT(src, IsConcept(_A("greater_than_with_requires"))); - REQUIRE_THAT(src, IsConcept(_A("max_four_bytes"))); - REQUIRE_THAT(src, IsConcept(_A("iterable"))); - REQUIRE_THAT(src, IsConcept(_A("has_value_type"))); - REQUIRE_THAT(src, IsConcept(_A("convertible_to_string"))); - REQUIRE_THAT(src, IsConcept(_A("iterable_with_value_type"))); - REQUIRE_THAT(src, IsConcept(_A("iterable_or_small_value_type"))); - - REQUIRE_THAT(src, - IsConceptRequirement(_A("greater_than_with_requires"), - "sizeof (l) > sizeof (r)")); - - REQUIRE_THAT( - src, IsConceptRequirement(_A("iterable"), "container.begin()")); - REQUIRE_THAT( - src, IsConceptRequirement(_A("iterable"), "container.end()")); + REQUIRE(IsConceptRequirement(src, "iterable", "container.begin()")); + REQUIRE(IsConceptRequirement(src, "iterable", "container.end()")); #if (LLVM_VERSION_MAJOR == 13) || (LLVM_VERSION_MAJOR == 14) - REQUIRE_THAT(src, - IsConceptRequirement( - _A("convertible_to_string"), "std::string({s})")); + REQUIRE(IsConceptRequirement( + src, "convertible_to_string", "std::string({s})")); #else - REQUIRE_THAT(src, + REQUIRE( IsConceptRequirement( - _A("convertible_to_string"), "std::string{s}")); + src,"convertible_to_string", "std::string{s}")); #endif - REQUIRE_THAT(src, - IsConceptRequirement(_A("convertible_to_string"), - "{std::to_string(s)} noexcept")); - REQUIRE_THAT(src, - IsConceptRequirement(_A("convertible_to_string"), - "{std::to_string(s)} -> std::same_as")); + REQUIRE(IsConceptRequirement( + src, "convertible_to_string", "{std::to_string(s)} noexcept")); + REQUIRE(IsConceptRequirement(src, "convertible_to_string", + "{std::to_string(s)} -> std::same_as")); - // Check if class templates exist - REQUIRE_THAT(src, IsClassTemplate("A", "max_four_bytes T")); - REQUIRE_THAT(src, IsClassTemplate("B", "T")); - REQUIRE_THAT(src, IsClassTemplate("C", "convertible_to_string T")); - REQUIRE_THAT( - src, IsClassTemplate("D", "iterable T1,T2,iterable T3,T4,T5")); - REQUIRE_THAT(src, IsClassTemplate("E", "T1,T2,T3")); - REQUIRE_THAT(src, IsClassTemplate("F", "T1,T2,T3")); + REQUIRE(IsClassTemplate(src, "A")); - // Check if all relationships exist - REQUIRE_THAT(src, - IsConstraint( - _A("A"), _A("max_four_bytes"), "T")); + REQUIRE(IsClassTemplate(src, "B")); + REQUIRE(IsClassTemplate(src, "C")); + REQUIRE(IsClassTemplate(src, "D")); + REQUIRE(IsClassTemplate(src, "E")); + REQUIRE(IsClassTemplate(src, "F")); - REQUIRE_THAT(src, - IsConstraint(_A("D"), - _A("max_four_bytes"), "T2")); - REQUIRE_THAT(src, - IsConstraint(_A("D"), - _A("max_four_bytes"), "T5")); - REQUIRE_THAT(src, - IsConstraint(_A("D"), - _A("iterable"), "T1")); - REQUIRE_THAT(src, - IsConstraint(_A("D"), - _A("iterable"), "T3")); + REQUIRE( + IsConstraint(src, "A", "max_four_bytes", "T")); - REQUIRE_THAT(src, - IsConstraint(_A("iterable_with_value_type"), - _A("has_value_type"), "T")); + REQUIRE(IsConstraint(src, "D", + "max_four_bytes", "T2")); + REQUIRE(IsConstraint(src, "D", + "max_four_bytes", "T5")); + REQUIRE(IsConstraint( + src, "D", "iterable", "T1")); + REQUIRE(IsConstraint( + src, "D", "iterable", "T3")); - REQUIRE_THAT(src, - IsConstraint(_A("iterable_or_small_value_type"), - _A("max_four_bytes"), "T")); - REQUIRE_THAT(src, - IsConstraint(_A("iterable_or_small_value_type"), - _A("iterable_with_value_type"), "T")); + REQUIRE(IsConstraint( + src, "iterable_with_value_type", "has_value_type", "T")); - REQUIRE_THAT(src, - IsConstraint(_A("E"), - _A("greater_than_with_requires"), "T1,T3")); + REQUIRE(IsConstraint( + src, "iterable_or_small_value_type", "max_four_bytes", "T")); + REQUIRE(IsConstraint(src, "iterable_or_small_value_type", + "iterable_with_value_type", "T")); - REQUIRE_THAT(src, - IsConstraint( - _A("F"), _A("greater_than_simple"), "T1,T3")); + REQUIRE(IsConstraint( + src, "E", "greater_than_with_requires", "T1,T3")); - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsConcept(j, "greater_than_simple")); - REQUIRE(IsConcept(j, "greater_than_with_requires")); - REQUIRE(IsConcept(j, "max_four_bytes")); - REQUIRE(IsConcept(j, "iterable")); - REQUIRE(IsConcept(j, "has_value_type")); - REQUIRE(IsConcept(j, "convertible_to_string")); - REQUIRE(IsConcept(j, "iterable_with_value_type")); - REQUIRE(IsConcept(j, "iterable_or_small_value_type")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsConcept; - using mermaid::IsConceptRequirement; - using mermaid::IsConstraint; - - // Check if all classes exist - REQUIRE_THAT(src, IsConcept(_A("greater_than_simple"))); - REQUIRE_THAT(src, IsConcept(_A("greater_than_with_requires"))); - REQUIRE_THAT(src, IsConcept(_A("max_four_bytes"))); - REQUIRE_THAT(src, IsConcept(_A("iterable"))); - REQUIRE_THAT(src, IsConcept(_A("has_value_type"))); - REQUIRE_THAT(src, IsConcept(_A("convertible_to_string"))); - REQUIRE_THAT(src, IsConcept(_A("iterable_with_value_type"))); - REQUIRE_THAT(src, IsConcept(_A("iterable_or_small_value_type"))); - - REQUIRE_THAT(src, - IsConceptRequirement(_A("greater_than_with_requires"), - "sizeof (l) > sizeof (r)")); - - REQUIRE_THAT( - src, IsConceptRequirement(_A("iterable"), "container.begin()")); - REQUIRE_THAT( - src, IsConceptRequirement(_A("iterable"), "container.end()")); - -#if (LLVM_VERSION_MAJOR == 13) || (LLVM_VERSION_MAJOR == 14) - REQUIRE_THAT(src, - IsConceptRequirement( - _A("convertible_to_string"), "std::string({s})")); -#else - REQUIRE_THAT(src, - IsConceptRequirement( - _A("convertible_to_string"), "std::string{s}")); -#endif - REQUIRE_THAT(src, - IsConceptRequirement(_A("convertible_to_string"), - "{std::to_string(s)} noexcept")); - REQUIRE_THAT(src, - IsConceptRequirement(_A("convertible_to_string"), - "{std::to_string(s)} -> std::same_as")); - - // Check if class templates exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - - // Check if all relationships exist - REQUIRE_THAT(src, - IsConstraint( - _A("A"), _A("max_four_bytes"), "T")); - - REQUIRE_THAT(src, - IsConstraint(_A("D"), - _A("max_four_bytes"), "T2")); - REQUIRE_THAT(src, - IsConstraint(_A("D"), - _A("max_four_bytes"), "T5")); - REQUIRE_THAT(src, - IsConstraint(_A("D"), - _A("iterable"), "T1")); - REQUIRE_THAT(src, - IsConstraint(_A("D"), - _A("iterable"), "T3")); - - REQUIRE_THAT(src, - IsConstraint(_A("iterable_with_value_type"), - _A("has_value_type"), "T")); - - REQUIRE_THAT(src, - IsConstraint(_A("iterable_or_small_value_type"), - _A("max_four_bytes"), "T")); - REQUIRE_THAT(src, - IsConstraint(_A("iterable_or_small_value_type"), - _A("iterable_with_value_type"), "T")); - - REQUIRE_THAT(src, - IsConstraint(_A("E"), - _A("greater_than_with_requires"), "T1,T3")); - - REQUIRE_THAT(src, - IsConstraint( - _A("F"), _A("greater_than_simple"), "T1,T3")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsConstraint( + src, "F", "greater_than_simple", "T1,T3")); + }); } \ No newline at end of file diff --git a/tests/t00057/test_case.h b/tests/t00057/test_case.h index 1a7331ea..662c6606 100644 --- a/tests/t00057/test_case.h +++ b/tests/t00057/test_case.h @@ -16,98 +16,33 @@ * limitations under the License. */ -TEST_CASE("t00057", "[test-case][class]") +TEST_CASE("t00057") { - auto [config, db] = load_config("t00057"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00057_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00057", "t00057_class"); - REQUIRE(diagram->name == "t00057_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "t00057_A")); + REQUIRE(IsClass(src, "t00057_B")); + REQUIRE(IsClass(src, "t00057_C")); + REQUIRE(IsUnion(src, "t00057_D")); + REQUIRE(IsClass(src, "t00057_E")); + REQUIRE(IsClass(src, "t00057_F")); + REQUIRE(IsClass(src, "t00057_G")); + REQUIRE(!IsClass(src, "(anonymous)")); + REQUIRE(IsClass(src, "t00057_R")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00057_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("t00057_A"))); - REQUIRE_THAT(src, IsClass(_A("t00057_B"))); - REQUIRE_THAT(src, IsClass(_A("t00057_C"))); - REQUIRE_THAT(src, IsUnion(_A("t00057_D"))); - REQUIRE_THAT(src, IsClass(_A("t00057_E"))); - REQUIRE_THAT(src, IsClass(_A("t00057_F"))); - REQUIRE_THAT(src, IsClass(_A("t00057_G"))); - REQUIRE_THAT(src, !IsClass(_A("(anonymous)"))); - REQUIRE_THAT(src, IsClass(_A("t00057_R"))); - - // Check if all relationships exist - REQUIRE_THAT(src, IsAggregation(_A("t00057_R"), _A("t00057_A"), "+a")); - REQUIRE_THAT(src, IsAggregation(_A("t00057_R"), _A("t00057_B"), "+b")); - REQUIRE_THAT(src, IsAssociation(_A("t00057_R"), _A("t00057_C"), "+c")); - REQUIRE_THAT(src, IsAggregation(_A("t00057_R"), _A("t00057_D"), "+d")); - REQUIRE_THAT(src, IsAssociation(_A("t00057_R"), _A("t00057_E"), "+e")); - REQUIRE_THAT(src, IsAssociation(_A("t00057_R"), _A("t00057_F"), "+f")); - REQUIRE_THAT(src, - IsAggregation( - _A("t00057_E"), _A("t00057_E::(coordinates)"), "+coordinates")); - REQUIRE_THAT(src, - IsAggregation(_A("t00057_E"), _A("t00057_E::(height)"), "+height")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(get_element(j, "t00057_A").value()["type"] == "class"); - REQUIRE(get_element(j, "t00057_B").value()["type"] == "class"); - REQUIRE(get_element(j, "t00057_C").value()["type"] == "class"); - REQUIRE(get_element(j, "t00057_D").value()["type"] == "class"); - REQUIRE(get_element(j, "t00057_E").value()["type"] == "class"); - REQUIRE(get_element(j, "t00057_F").value()["type"] == "class"); - REQUIRE(get_element(j, "t00057_G").value()["type"] == "class"); - REQUIRE(get_element(j, "t00057_R").value()["type"] == "class"); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsUnion; - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("t00057_A"))); - REQUIRE_THAT(src, IsClass(_A("t00057_B"))); - REQUIRE_THAT(src, IsClass(_A("t00057_C"))); - REQUIRE_THAT(src, IsUnion(_A("t00057_D"))); - REQUIRE_THAT(src, IsClass(_A("t00057_E"))); - REQUIRE_THAT(src, IsClass(_A("t00057_F"))); - REQUIRE_THAT(src, IsClass(_A("t00057_G"))); - REQUIRE_THAT(src, !IsClass(_A("(anonymous)"))); - REQUIRE_THAT(src, IsClass(_A("t00057_R"))); - - // Check if all relationships exist - REQUIRE_THAT(src, IsAggregation(_A("t00057_R"), _A("t00057_A"), "+a")); - REQUIRE_THAT(src, IsAggregation(_A("t00057_R"), _A("t00057_B"), "+b")); - REQUIRE_THAT(src, IsAssociation(_A("t00057_R"), _A("t00057_C"), "+c")); - REQUIRE_THAT(src, IsAggregation(_A("t00057_R"), _A("t00057_D"), "+d")); - REQUIRE_THAT(src, IsAssociation(_A("t00057_R"), _A("t00057_E"), "+e")); - REQUIRE_THAT(src, IsAssociation(_A("t00057_R"), _A("t00057_F"), "+f")); - REQUIRE_THAT(src, - IsAggregation( - _A("t00057_E"), _A("t00057_E::(coordinates)"), "+coordinates")); - REQUIRE_THAT(src, - IsAggregation(_A("t00057_E"), _A("t00057_E::(height)"), "+height")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAggregation(src, "t00057_R", "t00057_A", "a")); + REQUIRE(IsAggregation(src, "t00057_R", "t00057_B", "b")); + REQUIRE(IsAssociation(src, "t00057_R", "t00057_C", "c")); + REQUIRE(IsAggregation(src, "t00057_R", "t00057_D", "d")); + REQUIRE(IsAssociation(src, "t00057_R", "t00057_E", "e")); + REQUIRE(IsAssociation(src, "t00057_R", "t00057_F", "f")); + REQUIRE(IsAggregation( + src, "t00057_E", "t00057_E::(coordinates)", "coordinates")); + REQUIRE(IsAggregation( + src, "t00057_E", "t00057_E::(height)", "height")); + }); } \ No newline at end of file diff --git a/tests/t00058/.clang-uml b/tests/t00058/.clang-uml index a49be4ca..b238602e 100644 --- a/tests/t00058/.clang-uml +++ b/tests/t00058/.clang-uml @@ -8,5 +8,8 @@ diagrams: - clanguml::t00058 using_namespace: clanguml::t00058 plantuml: + after: + - '{{ alias("same_as_first_type") }} ..> {{ alias("first_type") }}' + mermaid: after: - '{{ alias("same_as_first_type") }} ..> {{ alias("first_type") }}' \ No newline at end of file diff --git a/tests/t00058/test_case.h b/tests/t00058/test_case.h index 1a31bb60..cceb976b 100644 --- a/tests/t00058/test_case.h +++ b/tests/t00058/test_case.h @@ -16,108 +16,48 @@ * limitations under the License. */ -TEST_CASE("t00058", "[test-case][class]") +TEST_CASE("t00058") { - auto [config, db] = load_config("t00058"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00058_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00058", "t00058_class"); - REQUIRE(diagram->name == "t00058_class"); + CHECK_CLASS_DIAGRAM( + config, diagram, *model, + [](const auto &src) { + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate( + src, "B>")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsConcept(src, "same_as_first_type")); - REQUIRE(model->name() == "t00058_class"); + REQUIRE(IsConstraint(src, "A", + "same_as_first_type", "T,Args...")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsConstraint(src, "B", + "same_as_first_type", "T,Args...")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(IsAggregation( + src, "R", "A", "aa")); + REQUIRE(IsAggregation( + src, "R", "B>", "bb")); - REQUIRE_THAT(src, IsClassTemplate("A", "int,int,double,std::string")); - REQUIRE_THAT( - src, IsClassTemplate("B", "int,std::string,int,double,A")); - - REQUIRE_THAT(src, IsConcept(_A("same_as_first_type"))); - - REQUIRE_THAT(src, - IsConstraint(_A("A"), - _A("same_as_first_type"), "T,Args...")); - - REQUIRE_THAT(src, - IsConstraint(_A("B"), - _A("same_as_first_type"), "T,Args...")); - - REQUIRE_THAT(src, - IsAggregation(_A("R"), _A("A"), "+aa")); - REQUIRE_THAT(src, - IsAggregation(_A("R"), - _A("B>"), "+bb")); - - REQUIRE_THAT(src, - IsInstantiation( - _A("A"), _A("A"))); - REQUIRE_THAT(src, - IsInstantiation(_A("B"), - _A("B>"))); - - REQUIRE_THAT(src, - IsDependency(_A("same_as_first_type"), - _A("first_type"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B>")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsConcept; - using mermaid::IsConstraint; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT( - src, IsClass(_A("B>"))); - - REQUIRE_THAT(src, IsConcept(_A("same_as_first_type"))); - - REQUIRE_THAT(src, - IsConstraint(_A("A"), - _A("same_as_first_type"), "T,Args...")); - - REQUIRE_THAT(src, - IsConstraint(_A("B"), - _A("same_as_first_type"), "T,Args...")); - - REQUIRE_THAT(src, - IsAggregation(_A("R"), _A("A"), "+aa")); - REQUIRE_THAT(src, - IsAggregation(_A("R"), - _A("B>"), "+bb")); - - REQUIRE_THAT(src, - IsInstantiation( - _A("A"), _A("A"))); - REQUIRE_THAT(src, - IsInstantiation(_A("B"), - _A("B>"))); - - // TODO - // REQUIRE_THAT(src, - // IsDependency(_A("same_as_first_type"), - // _A("first_type"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsInstantiation( + src, "A", "A")); + REQUIRE(IsInstantiation(src, "B", + "B>")); + }, + [](const plantuml_t &src) { + // TODO: This dependency has to be added manually in config file + // so it doesn't work in JSON + REQUIRE(IsDependency( + src, "same_as_first_type", "first_type")); + }, + [](const mermaid_t &src) { + // TODO: This dependency has to be added manually in config file + // so it doesn't work in JSON + REQUIRE(IsDependency( + src, "same_as_first_type", "first_type")); + }); } \ No newline at end of file diff --git a/tests/t00059/test_case.h b/tests/t00059/test_case.h index 851b1e87..9d6899c0 100644 --- a/tests/t00059/test_case.h +++ b/tests/t00059/test_case.h @@ -16,150 +16,52 @@ * limitations under the License. */ -TEST_CASE("t00059", "[test-case][class]") +TEST_CASE("t00059") { - auto [config, db] = load_config("t00059"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00059_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00059", "t00059_class"); - REQUIRE(diagram->name == "t00059_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsConcept(src, "fruit_c")); + REQUIRE(IsConcept(src, "apple_c")); + REQUIRE(IsConcept(src, "orange_c")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsConstraint(src, "apple_c", "fruit_c", "T", "up")); + REQUIRE(IsConstraint(src, "orange_c", "fruit_c", "T", "up")); - REQUIRE(model->name() == "t00059_class"); + REQUIRE(IsConceptRequirement(src, "apple_c", "t.get_sweetness()")); + REQUIRE(IsConceptRequirement(src, "orange_c", "t.get_bitterness()")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsClass(src, "gala_apple")); + REQUIRE(IsClass(src, "empire_apple")); + REQUIRE(IsClass(src, "valencia_orange")); + REQUIRE(IsClass(src, "lima_orange")); + REQUIRE(IsClass(src, "R")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(IsClassTemplate(src, "fruit_factory")); - REQUIRE_THAT(src, IsConcept(_A("fruit_c"))); - REQUIRE_THAT(src, IsConcept(_A("apple_c"))); - REQUIRE_THAT(src, IsConcept(_A("orange_c"))); + REQUIRE(IsDependency(src, "fruit_factory", + "gala_apple", "up")); + REQUIRE(IsDependency(src, "fruit_factory", + "valencia_orange", "up")); - REQUIRE_THAT( - src, IsConstraint(_A("apple_c"), _A("fruit_c"), "T", "up")); - REQUIRE_THAT( - src, IsConstraint(_A("orange_c"), _A("fruit_c"), "T", "up")); + REQUIRE(IsDependency(src, "fruit_factory", + "empire_apple", "up")); + REQUIRE(IsDependency(src, "fruit_factory", + "lima_orange", "up")); - REQUIRE_THAT( - src, IsConceptRequirement(_A("apple_c"), "t.get_sweetness()")); - REQUIRE_THAT( - src, IsConceptRequirement(_A("apple_c"), "t.get_bitterness()")); + REQUIRE(IsAggregation(src, "R", + "fruit_factory", "factory_1", "", "", + "up")); + REQUIRE(IsAggregation(src, "R", + "fruit_factory", "factory_2", "", "", + "up")); - REQUIRE_THAT(src, IsClass(_A("gala_apple"))); - REQUIRE_THAT(src, IsClass(_A("empire_apple"))); - REQUIRE_THAT(src, IsClass(_A("valencia_orange"))); - REQUIRE_THAT(src, IsClass(_A("lima_orange"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT( - src, IsClassTemplate("fruit_factory", "apple_c TA,orange_c TO")); - - REQUIRE_THAT(src, - IsDependency(_A("fruit_factory"), - _A("gala_apple"), "up")); - REQUIRE_THAT(src, - IsDependency(_A("fruit_factory"), - _A("valencia_orange"), "up")); - - REQUIRE_THAT(src, - IsDependency(_A("fruit_factory"), - _A("empire_apple"), "up")); - REQUIRE_THAT(src, - IsDependency(_A("fruit_factory"), - _A("lima_orange"), "up")); - - REQUIRE_THAT(src, - IsAggregation(_A("R"), - _A("fruit_factory"), "+factory_1", - "", "", "up")); - REQUIRE_THAT(src, - IsAggregation(_A("R"), - _A("fruit_factory"), "+factory_2", "", - "", "up")); - - REQUIRE_THAT(src, - IsInstantiation(_A("fruit_factory"), - _A("fruit_factory"), "up")); - REQUIRE_THAT(src, - IsInstantiation(_A("fruit_factory"), - _A("fruit_factory"), "up")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsConcept(j, "fruit_c")); - REQUIRE(IsConcept(j, "apple_c")); - REQUIRE(IsConcept(j, "orange_c")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsConcept; - using mermaid::IsConceptRequirement; - using mermaid::IsConstraint; - - REQUIRE_THAT(src, IsConcept(_A("fruit_c"))); - REQUIRE_THAT(src, IsConcept(_A("apple_c"))); - REQUIRE_THAT(src, IsConcept(_A("orange_c"))); - - REQUIRE_THAT( - src, IsConstraint(_A("apple_c"), _A("fruit_c"), "T")); - REQUIRE_THAT( - src, IsConstraint(_A("orange_c"), _A("fruit_c"), "T")); - - REQUIRE_THAT( - src, IsConceptRequirement(_A("apple_c"), "t.get_sweetness()")); - REQUIRE_THAT( - src, IsConceptRequirement(_A("apple_c"), "t.get_bitterness()")); - - REQUIRE_THAT(src, IsClass(_A("gala_apple"))); - REQUIRE_THAT(src, IsClass(_A("empire_apple"))); - REQUIRE_THAT(src, IsClass(_A("valencia_orange"))); - REQUIRE_THAT(src, IsClass(_A("lima_orange"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsClass(_A("fruit_factory"))); - - REQUIRE_THAT(src, - IsDependency(_A("fruit_factory"), - _A("gala_apple"))); - REQUIRE_THAT(src, - IsDependency(_A("fruit_factory"), - _A("valencia_orange"))); - - REQUIRE_THAT(src, - IsDependency(_A("fruit_factory"), - _A("empire_apple"))); - REQUIRE_THAT(src, - IsDependency(_A("fruit_factory"), - _A("lima_orange"))); - - REQUIRE_THAT(src, - IsAggregation(_A("R"), - _A("fruit_factory"), "+factory_1")); - REQUIRE_THAT(src, - IsAggregation(_A("R"), - _A("fruit_factory"), "+factory_2")); - - REQUIRE_THAT(src, - IsInstantiation(_A("fruit_factory"), - _A("fruit_factory"))); - REQUIRE_THAT(src, - IsInstantiation(_A("fruit_factory"), - _A("fruit_factory"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsInstantiation(src, "fruit_factory", + "fruit_factory", "up")); + REQUIRE(IsInstantiation(src, "fruit_factory", + "fruit_factory", "up")); + }); } \ No newline at end of file diff --git a/tests/t00060/test_case.h b/tests/t00060/test_case.h index 528bfcd4..de813fdf 100644 --- a/tests/t00060/test_case.h +++ b/tests/t00060/test_case.h @@ -16,71 +16,22 @@ * limitations under the License. */ -TEST_CASE("t00060", "[test-case][class]") +TEST_CASE("t00060") { - auto [config, db] = load_config("t00060"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00060_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00060", "t00060_class"); - REQUIRE(diagram->name == "t00060_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(!IsClass(src, "E")); + REQUIRE(!IsClass(src, "F")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00060_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, !IsClass(_A("E"))); - REQUIRE_THAT(src, !IsClass(_A("F"))); - - // Check if class templates exist - REQUIRE_THAT(src, IsClassTemplate("G", "T")); - REQUIRE_THAT(src, IsClassTemplate("H", "T,P")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsClass(j, "D")); - REQUIRE(!IsClass(j, "E")); - REQUIRE(!IsClass(j, "F")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, !IsClass(_A("E"))); - REQUIRE_THAT(src, !IsClass(_A("F"))); - - // Check if class templates exist - REQUIRE_THAT(src, IsClass(_A("G"))); - REQUIRE_THAT(src, IsClass(_A("H"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsClassTemplate(src, "G")); + REQUIRE(IsClassTemplate(src, "H")); + }); } \ No newline at end of file diff --git a/tests/t00061/test_case.h b/tests/t00061/test_case.h index 64b5fdb1..847cfc6d 100644 --- a/tests/t00061/test_case.h +++ b/tests/t00061/test_case.h @@ -16,54 +16,16 @@ * limitations under the License. */ -TEST_CASE("t00061", "[test-case][class]") +TEST_CASE("t00061") { - auto [config, db] = load_config("t00061"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00061_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00061", "t00061_class"); - REQUIRE(diagram->name == "t00061_class"); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00061_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, !IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("C"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(!IsClass(j, "B")); - REQUIRE(!IsClass(j, "C")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, !IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("C"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(!IsClass(src, "B")); + REQUIRE(!IsClass(src, "C")); + }); } \ No newline at end of file diff --git a/tests/t00062/test_case.h b/tests/t00062/test_case.h index afa222c1..198b875c 100644 --- a/tests/t00062/test_case.h +++ b/tests/t00062/test_case.h @@ -16,137 +16,57 @@ * limitations under the License. */ -TEST_CASE("t00062", "[test-case][class]") +TEST_CASE("t00062") { - auto [config, db] = load_config("t00062"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00062_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00062", "t00062_class"); - REQUIRE(diagram->name == "t00062_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!src.contains("type-parameter-")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); - REQUIRE(model->name() == "t00062_class"); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A>")); + REQUIRE(IsClassTemplate(src, "A>")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(IsField(src, "A", "u", "U &")); + REQUIRE(IsField(src, "A", "u", "U ***")); + REQUIRE(IsField(src, "A", "u", "U &&")); + REQUIRE(IsField(src, "A", "u", "const U &")); + REQUIRE(IsField(src, "A", "m", "M C::*")); - REQUIRE_THAT(src, !Contains("type-parameter-")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); - // Check if all classes exist - REQUIRE_THAT(src, IsClassTemplate("A", "T")); - REQUIRE_THAT(src, IsClassTemplate("A", "U &")); - REQUIRE_THAT(src, IsClassTemplate("A", "U &&")); - REQUIRE_THAT(src, IsClassTemplate("A", "U const&")); - REQUIRE_THAT(src, IsClassTemplate("A", "M C::*")); - REQUIRE_THAT(src, IsClassTemplate("A", "M C::* &&")); - REQUIRE_THAT(src, IsClassTemplate("A", "M (C::*)(Arg)")); - REQUIRE_THAT(src, IsClassTemplate("A", "int (C::*)(bool)")); - REQUIRE_THAT(src, IsClassTemplate("A", "M (C::*)(Arg) &&")); - REQUIRE_THAT(src, IsClassTemplate("A", "M (C::*)(Arg1,Arg2,Arg3)")); - REQUIRE_THAT(src, IsClassTemplate("A", "float (C::*)(int) &&")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE( + IsInstantiation(src, "A", "A")); - REQUIRE_THAT(src, IsClassTemplate("A", "char[N]")); - REQUIRE_THAT(src, IsClassTemplate("A", "char[1000]")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); - REQUIRE_THAT(src, IsClassTemplate("A", "U(...)")); - REQUIRE_THAT(src, IsClassTemplate("A", "C")); - REQUIRE_THAT(src, IsClassTemplate("A", "C")); - - REQUIRE_THAT(src, (IsField("u", "U &"))); - REQUIRE_THAT(src, (IsField("u", "U **"))); - REQUIRE_THAT(src, (IsField("u", "U ***"))); - REQUIRE_THAT(src, (IsField("u", "U &&"))); - REQUIRE_THAT(src, (IsField("u", "const U &"))); - REQUIRE_THAT(src, (IsField("c", "C &"))); - REQUIRE_THAT(src, (IsField("m", "M C::*"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, - IsInstantiation(_A("A"), _A("A"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A>"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A>"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsField; - - REQUIRE_THAT(src, !Contains("type-parameter-")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("A>"))); - REQUIRE_THAT(src, IsClass(_A("A>"))); - - REQUIRE_THAT(src, (IsField("u", "U &"))); - REQUIRE_THAT(src, (IsField("u", "U **"))); - REQUIRE_THAT(src, (IsField("u", "U ***"))); - REQUIRE_THAT(src, (IsField("u", "U &&"))); - REQUIRE_THAT(src, (IsField("u", "const U &"))); - REQUIRE_THAT(src, (IsField("c", "C &"))); - REQUIRE_THAT(src, (IsField("m", "M C::*"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, - IsInstantiation(_A("A"), _A("A"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT( - src, IsInstantiation(_A("A"), _A("A"))); - - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A>"))); - REQUIRE_THAT(src, IsInstantiation(_A("A"), _A("A>"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A")); + REQUIRE(IsInstantiation(src, "A", "A>")); + REQUIRE(IsInstantiation(src, "A", "A>")); + }); } \ No newline at end of file diff --git a/tests/t00063/test_case.h b/tests/t00063/test_case.h index 8eac17bc..c66ae44e 100644 --- a/tests/t00063/test_case.h +++ b/tests/t00063/test_case.h @@ -16,53 +16,16 @@ * limitations under the License. */ -TEST_CASE("t00063", "[test-case][class]") +TEST_CASE("t00063") { - auto [config, db] = load_config("t00063"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00063_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00063", "t00063_class"); - REQUIRE(diagram->name == "t00063_class"); - - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00063_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, !IsEnum(_A("B"))); - REQUIRE_THAT(src, !IsEnum(_A("C"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(!IsEnum(j, "B")); - REQUIRE(!IsEnum(j, "C")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsEnum; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, !IsEnum(_A("B"))); - REQUIRE_THAT(src, !IsEnum(_A("C"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(!IsEnum(src, "B")); + REQUIRE(!IsEnum(src, "C")); + }); } \ No newline at end of file diff --git a/tests/t00064/test_case.h b/tests/t00064/test_case.h index c813798a..de0d9fd6 100644 --- a/tests/t00064/test_case.h +++ b/tests/t00064/test_case.h @@ -16,125 +16,55 @@ * limitations under the License. */ -TEST_CASE("t00064", "[test-case][class]") +TEST_CASE("t00064") { - auto [config, db] = load_config("t00064"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00064_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00064", "t00064_class"); - REQUIRE(diagram->name == "t00064_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!src.contains("type-parameter-")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "R")); - REQUIRE(model->name() == "t00064_class"); + REQUIRE(IsClassTemplate(src, "type_list")); + REQUIRE(IsClassTemplate(src, "type_list")); + REQUIRE(IsClassTemplate(src, "type_list")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsClassTemplate(src, "head")); + REQUIRE(IsClassTemplate(src, "head>")); + REQUIRE(IsClassTemplate(src, "type_group_pair")); + REQUIRE(IsClassTemplate( + src, "type_group_pair,type_list>")); + REQUIRE(IsClassTemplate( + src, "type_group_pair,type_list>")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(IsClassTemplate(src, "optional_ref")); - REQUIRE_THAT(src, !Contains("type-parameter-")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsClassTemplate("type_list", "Ts...")); - REQUIRE_THAT(src, IsClassTemplate("type_list", "Ret(Arg &&),Ts...")); - REQUIRE_THAT(src, IsClassTemplate("type_list", "T const,Ts...")); - - REQUIRE_THAT(src, IsClassTemplate("head", "typename")); - REQUIRE_THAT(src, IsClassTemplate("head", "type_list")); - REQUIRE_THAT( - src, IsClassTemplate("type_group_pair", "typename,typename")); - REQUIRE_THAT(src, - IsClassTemplate( - "type_group_pair", "type_list,type_list")); - REQUIRE_THAT(src, - IsClassTemplate( - "type_group_pair", "type_list,type_list")); - - REQUIRE_THAT(src, IsClassTemplate("optional_ref", "T")); - - REQUIRE_THAT(src, - IsClassTemplate("type_group_pair_it", - "It,type_list,type_list")); - REQUIRE_THAT(src, (IsMethod("get", "ref_t", "unsigned int i"))); + REQUIRE(IsClassTemplate(src, + "type_group_pair_it,type_list>")); + REQUIRE(IsMethod(src, + "type_group_pair_it,type_list>", + "get", "ref_t", "unsigned int i")); #if LLVM_VERSION_MAJOR < 16 - REQUIRE_THAT(src, - (IsMethod("getp", "value_type const*", "unsigned int i"))); - REQUIRE_THAT(src, - (IsMethod( - "find", "unsigned int", "value_type const& v"))); + REQUIRE(IsMethod(src, + "type_group_pair_it,type_list>", + "getp", "value_type const*", "unsigned int i")); + REQUIRE(IsMethod(src, + "type_group_pair_it,type_list>", + "find", "unsigned int", "value_type const& v")); #else - REQUIRE_THAT(src, - (IsMethod("getp", "const value_type *", "unsigned int i"))); - REQUIRE_THAT(src, - (IsMethod( - "find", "unsigned int", "const value_type & v"))); - + REQUIRE( + IsMethod(src, + "type_group_pair_it,type_list>", + "getp", "const value_type *", "unsigned int i")); + REQUIRE( + IsMethod(src,"type_group_pair_it,type_list>", + "find", "unsigned int", "const value_type & v")); #endif - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsMethod; - - REQUIRE_THAT(src, !Contains("type-parameter-")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsClass(_A("type_list"))); - REQUIRE_THAT(src, IsClass(_A("type_list"))); - REQUIRE_THAT(src, IsClass(_A("type_list"))); - - REQUIRE_THAT(src, IsClass(_A("head"))); - REQUIRE_THAT(src, IsClass(_A("head>"))); - REQUIRE_THAT(src, IsClass(_A("type_group_pair"))); - REQUIRE_THAT(src, - IsClass(_A( - "type_group_pair,type_list>"))); - REQUIRE_THAT(src, - IsClass(_A( - "type_group_pair,type_list>"))); - - REQUIRE_THAT(src, IsClass(_A("optional_ref"))); - - REQUIRE_THAT(src, - IsClass(_A("type_group_pair_it,type_list<" - "Second...>>"))); - REQUIRE_THAT(src, (IsMethod("get", "ref_t", "unsigned int i"))); -#if LLVM_VERSION_MAJOR < 16 - REQUIRE_THAT(src, - (IsMethod("getp", "value_type const*", "unsigned int i"))); - REQUIRE_THAT(src, - (IsMethod( - "find", "unsigned int", "value_type const& v"))); -#else - REQUIRE_THAT(src, - (IsMethod("getp", "const value_type *", "unsigned int i"))); - REQUIRE_THAT(src, - (IsMethod( - "find", "unsigned int", "const value_type & v"))); - -#endif - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + }); } \ No newline at end of file diff --git a/tests/t00065/test_case.h b/tests/t00065/test_case.h index 51ccc4c5..00da8823 100644 --- a/tests/t00065/test_case.h +++ b/tests/t00065/test_case.h @@ -16,60 +16,24 @@ * limitations under the License. */ -TEST_CASE("t00065", "[test-case][class]") +TEST_CASE("t00065") { - auto [config, db] = load_config("t00065"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t00065_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00065", "t00065_class"); - REQUIRE(diagram->name == "t00065_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "R")); + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, {"detail", "AImpl"})); + REQUIRE(IsEnum(src, "XYZ")); + REQUIRE(IsEnum(src, "ABC")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00065_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("R"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("detail::AImpl"))); - REQUIRE_THAT(src, IsEnum(_A("XYZ"))); - REQUIRE_THAT(src, IsEnum(_A("ABC"))); - - REQUIRE_THAT(src, IsPackage("module1")); - REQUIRE_THAT(src, IsPackage("module2")); - REQUIRE_THAT(src, IsPackage("submodule1a")); - REQUIRE_THAT(src, IsPackage("concepts")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsEnum; - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("R"))); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("detail::AImpl"))); - REQUIRE_THAT(src, IsEnum(_A("XYZ"))); - REQUIRE_THAT(src, IsEnum(_A("ABC"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDirectoryPackage(src, "module1"s)); + REQUIRE(IsDirectoryPackage(src, "module2"s)); + REQUIRE(IsDirectoryPackage(src, "module1"s, "submodule1a"s)); + REQUIRE(IsDirectoryPackage(src, "module2"s, "concepts"s)); + }); } \ No newline at end of file diff --git a/tests/t00066/test_case.h b/tests/t00066/test_case.h index 37765b71..4f930b04 100644 --- a/tests/t00066/test_case.h +++ b/tests/t00066/test_case.h @@ -16,110 +16,43 @@ * limitations under the License. */ -TEST_CASE("t00066", "[test-case][class]") +TEST_CASE("t00066") { - auto [config, db] = load_config("t00066"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00066_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00066", "t00066_class"); - REQUIRE(diagram->name == "t00066_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(!IsDependency(src, "A", "A")); - REQUIRE(model->name() == "t00066_class"); + REQUIRE(IsMethod(src, "A", "A")); + REQUIRE(IsMethod(src, "A", "A", "void", "A &&")); + REQUIRE(IsMethod(src, "A", "A", "void", "const A &")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsMethod(src, "A", "~A")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(IsMethod(src, "A", "basic_method")); + REQUIRE(IsMethod(src, "A", "static_method", "int")); + REQUIRE(IsMethod(src, "A", "const_method")); + REQUIRE(IsMethod(src, "A", "default_int", "int", "int i = 12")); + REQUIRE(IsMethod(src, "A", "default_string", "std::string", + "int i, std::string s = \"abc\"")); - REQUIRE_THAT(src, IsClass(_A("A"))); + REQUIRE(IsMethod(src, "A", "size", "std::size_t")); - REQUIRE_THAT(src, !IsDependency(_A("A"), _A("A"))); + REQUIRE(IsMethod(src, "A", "protected_method")); + REQUIRE(IsMethod(src, "A", "private_method")); + REQUIRE(IsField(src, "A", "public_member", "int")); + REQUIRE(IsField(src, "A", "protected_member", "int")); + REQUIRE(IsField(src, "A", "private_member", "int")); + REQUIRE(IsField( + src, "A", "auto_member", "const unsigned long")); - REQUIRE_THAT(src, (IsMethod("A"))); - REQUIRE_THAT(src, (IsMethod("A", "void", "A &&"))); - REQUIRE_THAT( - src, (IsMethod("A", "void", "const A &"))); - - REQUIRE_THAT(src, (IsMethod("~A"))); - - REQUIRE_THAT(src, (IsMethod("basic_method"))); - REQUIRE_THAT(src, (IsMethod("static_method", "int"))); - REQUIRE_THAT(src, (IsMethod("const_method"))); - REQUIRE_THAT( - src, (IsMethod("default_int", "int", "int i = 12"))); - REQUIRE_THAT(src, - (IsMethod("default_string", "std::string", - "int i, std::string s = \"abc\""))); - - REQUIRE_THAT(src, (IsMethod("size", "std::size_t"))); - - REQUIRE_THAT(src, (IsMethod("protected_method"))); - REQUIRE_THAT(src, (IsMethod("private_method"))); - REQUIRE_THAT(src, (IsField("public_member", "int"))); - REQUIRE_THAT(src, (IsField("protected_member", "int"))); - REQUIRE_THAT(src, (IsField("private_member", "int"))); - REQUIRE_THAT(src, - (IsField("auto_member", "const unsigned long"))); - - REQUIRE_THAT(src, (IsField("a_", "int"))); - REQUIRE_THAT(src, (IsField("b_", "int"))); - REQUIRE_THAT(src, (IsField("c_", "int"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsField; - using mermaid::IsMethod; - - REQUIRE_THAT(src, IsClass(_A("A"))); - - REQUIRE_THAT(src, !IsDependency(_A("A"), _A("A"))); - - REQUIRE_THAT(src, (IsMethod("A"))); - REQUIRE_THAT(src, (IsMethod("A", "void", "A &&"))); - REQUIRE_THAT( - src, (IsMethod("A", "void", "const A &"))); - - REQUIRE_THAT(src, (IsMethod("~A"))); - - REQUIRE_THAT(src, (IsMethod("basic_method"))); - REQUIRE_THAT(src, (IsMethod("static_method", "int"))); - REQUIRE_THAT(src, (IsMethod("const_method"))); - REQUIRE_THAT( - src, (IsMethod("default_int", "int", "int i = 12"))); - REQUIRE_THAT(src, - (IsMethod("default_string", "std::string", - "int i, std::string s = \"abc\""))); - - REQUIRE_THAT(src, (IsMethod("size", "std::size_t"))); - - REQUIRE_THAT(src, (IsMethod("protected_method"))); - REQUIRE_THAT(src, (IsMethod("private_method"))); - REQUIRE_THAT(src, (IsField("public_member", "int"))); - REQUIRE_THAT(src, (IsField("protected_member", "int"))); - REQUIRE_THAT(src, (IsField("private_member", "int"))); - REQUIRE_THAT(src, - (IsField("auto_member", "const unsigned long"))); - - REQUIRE_THAT(src, (IsField("a_", "int"))); - REQUIRE_THAT(src, (IsField("b_", "int"))); - REQUIRE_THAT(src, (IsField("c_", "int"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsField(src, "A", "a_", "int")); + REQUIRE(IsField(src, "A", "b_", "int")); + REQUIRE(IsField(src, "A", "c_", "int")); + }); } \ No newline at end of file diff --git a/tests/t00067/test_case.h b/tests/t00067/test_case.h index b1142a5b..5182cad3 100644 --- a/tests/t00067/test_case.h +++ b/tests/t00067/test_case.h @@ -16,60 +16,20 @@ * limitations under the License. */ -TEST_CASE("t00067", "[test-case][class]") +TEST_CASE("t00067") { - auto [config, db] = load_config("t00067"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00067_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00067", "t00067_class"); - REQUIRE(diagram->name == "t00067_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!IsMethod(src, "A", "A")); + REQUIRE(!IsMethod(src, "A", "void", "A &&")); + REQUIRE(!IsMethod(src, "A", "void", "const A &")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(!IsMethod(src, "A", "~A")); - REQUIRE(model->name() == "t00067_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, !(IsMethod("A"))); - REQUIRE_THAT(src, !(IsMethod("A", "void", "A &&"))); - REQUIRE_THAT( - src, !(IsMethod("A", "void", "const A &"))); - - REQUIRE_THAT(src, !(IsMethod("~A"))); - - REQUIRE_THAT(src, !(IsMethod("~A"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsMethod; - - REQUIRE_THAT(src, !(IsMethod("A"))); - REQUIRE_THAT(src, !(IsMethod("A", "void", "A &&"))); - REQUIRE_THAT( - src, !(IsMethod("A", "void", "const A &"))); - - REQUIRE_THAT(src, !(IsMethod("~A"))); - - REQUIRE_THAT(src, !(IsMethod("~A"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!IsMethod(src, "A", "~A")); + }); } \ No newline at end of file diff --git a/tests/t00068/test_case.h b/tests/t00068/test_case.h index 19836b1b..ab6bd96b 100644 --- a/tests/t00068/test_case.h +++ b/tests/t00068/test_case.h @@ -16,180 +16,68 @@ * limitations under the License. */ -TEST_CASE("t00068_r0", "[test-case][class][t00068]") +TEST_CASE("t00068_r0") { - auto [config, db] = load_config("t00068"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00068_r0_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00068", "t00068_r0_class"); - auto model = generate_class_diagram(*db, diagram); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!IsClass(src, "A")); + REQUIRE(!IsClass(src, "AA")); + REQUIRE(IsClass(src, "AAA")); - REQUIRE(model->name() == "t00068_r0_class"); + REQUIRE(!IsClass(src, "B")); + REQUIRE(!IsClass(src, "BB")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(!IsClass(src, "R")); + REQUIRE(!IsClass(src, "RR")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, !IsClass(_A("A"))); - REQUIRE_THAT(src, !IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("AAA"))); - - REQUIRE_THAT(src, !IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("BB"))); - - REQUIRE_THAT(src, !IsClass(_A("R"))); - REQUIRE_THAT(src, !IsClass(_A("RR"))); - - REQUIRE_THAT(src, !IsEnum(_A("AKind"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - using mermaid::IsEnum; - - REQUIRE_THAT(src, !IsClass(_A("A"))); - REQUIRE_THAT(src, !IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("AAA"))); - - REQUIRE_THAT(src, !IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("BB"))); - - REQUIRE_THAT(src, !IsClass(_A("R"))); - REQUIRE_THAT(src, !IsClass(_A("RR"))); - - REQUIRE_THAT(src, !IsEnum(_A("AKind"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!IsEnum(src, "AKind")); + }); } -TEST_CASE("t00068_r1", "[test-case][class][t00068]") +TEST_CASE("t00068_r1") { - auto [config, db] = load_config("t00068"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00068_r1_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00068", "t00068_r1_class"); - auto model = generate_class_diagram(*db, diagram); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!IsClass(src, "A")); + REQUIRE(IsClass(src, "AA")); + REQUIRE(IsClass(src, "AAA")); - REQUIRE(model->name() == "t00068_r1_class"); + REQUIRE(!IsClass(src, "B")); + REQUIRE(IsClass(src, "BB")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsClass(src, "R")); + REQUIRE(!IsClass(src, "RR")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, !IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("AAA"))); - - REQUIRE_THAT(src, !IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("BB"))); - - REQUIRE_THAT(src, IsClass(_A("R"))); - REQUIRE_THAT(src, !IsClass(_A("RR"))); - - REQUIRE_THAT(src, IsEnum(_A("AKind"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - - REQUIRE_THAT(src, !IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("AAA"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsEnum(src, "AKind")); + }); } -TEST_CASE("t00068_r2", "[test-case][class][t00068]") +TEST_CASE("t00068_r2") { - auto [config, db] = load_config("t00068"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00068_r2_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00068", "t00068_r2_class"); - auto model = generate_class_diagram(*db, diagram); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "AA")); + REQUIRE(IsClass(src, "AAA")); - REQUIRE(model->name() == "t00068_r2_class"); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "BB")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsClass(src, "R")); + REQUIRE(IsClass(src, "RR")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("AAA"))); - - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("BB"))); - - REQUIRE_THAT(src, IsClass(_A("R"))); - REQUIRE_THAT(src, IsClass(_A("RR"))); - - REQUIRE_THAT(src, IsEnum(_A("AKind"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - using mermaid::IsEnum; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("AA"))); - REQUIRE_THAT(src, IsClass(_A("AAA"))); - - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("BB"))); - - REQUIRE_THAT(src, IsClass(_A("R"))); - REQUIRE_THAT(src, IsClass(_A("RR"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsEnum(src, "AKind")); + }); } \ No newline at end of file diff --git a/tests/t00069/test_case.h b/tests/t00069/test_case.h index 069803e2..2f56279c 100644 --- a/tests/t00069/test_case.h +++ b/tests/t00069/test_case.h @@ -16,72 +16,27 @@ * limitations under the License. */ -TEST_CASE("t00069", "[test-case][class]") +TEST_CASE("t00069") { - auto [config, db] = load_config("t00069"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00069_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00069", "t00069_class"); - REQUIRE(diagram->name == "t00069_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClassTemplate(src, "generator")); - REQUIRE(model->name() == "t00069_class"); + REQUIRE(IsInnerClass(src, "generator", "generator::promise_type")); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsMethod( + src, "A", "iota", "generator")); + REQUIRE(IsMethod( + src, "A", "seed", "generator")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - - // Check if class templates exist - REQUIRE_THAT(src, IsClassTemplate("generator", "T")); - - // Check if all inner classes exist - REQUIRE_THAT(src, - IsInnerClass(_A("generator"), _A("generator::promise_type"))); - - // Check if all methods exist - REQUIRE_THAT(src, - (IsMethod("iota", "generator"))); - REQUIRE_THAT(src, - (IsMethod("seed", "generator"))); - - // Check if all relationships exist - REQUIRE_THAT( - src, IsDependency(_A("A"), _A("generator"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("generator"), _A("generator"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - using mermaid::IsMethod; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, - (IsMethod("iota", "generator"))); - REQUIRE_THAT(src, - (IsMethod("seed", "generator"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "A", "generator")); + REQUIRE( + IsInstantiation(src, "generator", "generator")); + }); } \ No newline at end of file diff --git a/tests/t00070/test_case.h b/tests/t00070/test_case.h index 59227728..edde2b70 100644 --- a/tests/t00070/test_case.h +++ b/tests/t00070/test_case.h @@ -16,74 +16,23 @@ * limitations under the License. */ -TEST_CASE("t00070", "[test-case][class]") +TEST_CASE("t00070") { - auto [config, db] = load_config("t00070"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00070_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00070", "t00070_class"); - REQUIRE(diagram->name == "t00070_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(!IsClass(src, "C")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClassTemplate(src, "BB")); + REQUIRE(!IsClassTemplate(src, "CC")); - REQUIRE(model->name() == "t00070_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("C"))); - - REQUIRE_THAT(src, IsClassTemplate("BB", "T")); - REQUIRE_THAT(src, !IsClassTemplate("CC", "T")); - - REQUIRE_THAT(src, IsEnum(_A("BBB"))); - REQUIRE_THAT(src, !IsClass(_A("BBBB"))); - REQUIRE_THAT(src, !IsEnum(_A("CCC"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(!IsClass(j, "C")); - - REQUIRE(InPublicModule(j, "A", "t00070")); - REQUIRE(InPublicModule(j, "B", "t00070.lib1")); - - REQUIRE(!IsClass(j, "BBBB")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - using mermaid::IsEnum; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, !IsClass(_A("C"))); - - REQUIRE_THAT(src, IsClass(_A("BB"))); - REQUIRE_THAT(src, !IsClass(_A("CC"))); - - REQUIRE_THAT(src, IsEnum(_A("BBB"))); - REQUIRE_THAT(src, !IsClass(_A("BBBB"))); - REQUIRE_THAT(src, !IsEnum(_A("CCC"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsEnum(src, "BBB")); + REQUIRE(!IsClass(src, "BBBB")); + REQUIRE(!IsEnum(src, "CCC")); + }); } \ No newline at end of file diff --git a/tests/t00071/test_case.h b/tests/t00071/test_case.h index 21821d2d..fcdec30b 100644 --- a/tests/t00071/test_case.h +++ b/tests/t00071/test_case.h @@ -16,61 +16,24 @@ * limitations under the License. */ -TEST_CASE("t00071", "[test-case][class]") +TEST_CASE("t00071") { - auto [config, db] = load_config("t00071"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t00071_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00071", "t00071_class"); - REQUIRE(diagram->name == "t00071_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "R")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsEnum(src, {"detail", "BBB"})); + REQUIRE(IsEnum(src, {"detail", "CCC"})); - REQUIRE(model->name() == "t00071_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsEnum(_A("detail::BBB"))); - REQUIRE_THAT(src, IsEnum(_A("detail::CCC"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsModulePackage(j, "app"s)); - REQUIRE(IsModulePackage(j, "app"s, "lib1"s)); - REQUIRE(IsModulePackage(j, "app"s, "lib1"s, "mod1"s)); - REQUIRE(IsModulePackage(j, "app"s, "lib1"s, "mod2"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - using mermaid::IsEnum; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsEnum(_A("detail::BBB"))); - REQUIRE_THAT(src, IsEnum(_A("detail::CCC"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsModulePackage(src, "app"s)); + REQUIRE(IsModulePackage(src, "app"s, "lib1"s)); + REQUIRE(IsModulePackage(src, "app"s, "lib1"s, "mod1"s)); + REQUIRE(IsModulePackage(src, "app"s, "lib1"s, "mod2"s)); + }); } \ No newline at end of file diff --git a/tests/t00072/test_case.h b/tests/t00072/test_case.h index 10252aed..87d29ab0 100644 --- a/tests/t00072/test_case.h +++ b/tests/t00072/test_case.h @@ -16,88 +16,31 @@ * limitations under the License. */ -TEST_CASE("t00072", "[test-case][class]") +TEST_CASE("t00072") { - auto [config, db] = load_config("t00072"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t00072_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00072", "t00072_class"); - REQUIRE(diagram->name == "t00072_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsModulePackage(src, "app"s)); + REQUIRE(IsModulePackage(src, "app"s, ":lib1"s)); + REQUIRE(IsModulePackage(src, "app"s, ":lib1"s, "mod1"s)); + REQUIRE(IsModulePackage(src, "app"s, ":lib1"s, "mod2"s)); + REQUIRE(IsModulePackage(src, "app"s, ":lib2"s)); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClassTemplate(src, "CC")); + REQUIRE(IsEnum(src, {"detail", "CCC"})); - REQUIRE(model->name() == "t00072_class"); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClassTemplate(src, "BB")); + REQUIRE(IsEnum(src, {"detail", "BBB"})); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsPackage("app")); - REQUIRE_THAT(src, IsPackage(":lib1")); - REQUIRE_THAT(src, IsPackage(":lib2")); - REQUIRE_THAT(src, IsPackage("mod1")); - REQUIRE_THAT(src, IsPackage("mod2")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClassTemplate("CC", "T")); - REQUIRE_THAT(src, IsEnum(_A("detail::CCC"))); - - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClassTemplate("BB", "T")); - REQUIRE_THAT(src, IsEnum(_A("detail::BBB"))); - - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsClass(j, "D")); - REQUIRE(IsEnum(j, "detail::CCC")); - REQUIRE(IsEnum(j, "detail::BBB")); - - REQUIRE(IsModulePackage(j, "app"s)); - REQUIRE(IsModulePackage(j, "app"s, ":lib1"s)); - REQUIRE(IsModulePackage(j, "app"s, ":lib1"s, "mod1"s)); - REQUIRE(IsModulePackage(j, "app"s, ":lib1"s, "mod2"s)); - REQUIRE(IsModulePackage(j, "app"s, ":lib2"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - using mermaid::IsEnum; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("CC"))); - REQUIRE_THAT(src, IsEnum(_A("detail::CCC"))); - - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("BB"))); - REQUIRE_THAT(src, IsEnum(_A("detail::BBB"))); - - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClass(src, "E")); + }); } \ No newline at end of file diff --git a/tests/t00073/test_case.h b/tests/t00073/test_case.h index 68af72fd..9491a1c9 100644 --- a/tests/t00073/test_case.h +++ b/tests/t00073/test_case.h @@ -16,81 +16,26 @@ * limitations under the License. */ -TEST_CASE("t00073", "[test-case][class]") +TEST_CASE("t00073") { - auto [config, db] = load_config("t00073"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00073_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00073", "t00073_class"); - REQUIRE(diagram->name == "t00073_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "AHandler")); + REQUIRE(IsClass(src, "BHandler")); + REQUIRE(IsClassTemplate(src, "Overload")); + REQUIRE(IsClassTemplate(src, "Overload")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00073_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("AHandler"))); - REQUIRE_THAT(src, IsClass(_A("BHandler"))); - REQUIRE_THAT(src, IsClassTemplate("Overload", "Bases...")); - REQUIRE_THAT(src, IsClassTemplate("Overload", "AHandler,BHandler")); - - REQUIRE_THAT(src, IsDependency(_A("AHandler"), _A("A"))); - REQUIRE_THAT(src, IsDependency(_A("BHandler"), _A("B"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("Overload"), _A("Overload"))); - REQUIRE_THAT(src, - IsAggregation( - _A("R"), _A("Overload"), "+dispatch")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClassTemplate(j, "Overload")); - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "AHandler")); - REQUIRE(IsClass(j, "BHandler")); - REQUIRE(IsClass(j, "Overload")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("AHandler"))); - REQUIRE_THAT(src, IsClass(_A("BHandler"))); - REQUIRE_THAT(src, IsClass(_A("Overload"))); - REQUIRE_THAT(src, IsClass(_A("Overload"))); - - REQUIRE_THAT(src, IsDependency(_A("AHandler"), _A("A"))); - REQUIRE_THAT(src, IsDependency(_A("BHandler"), _A("B"))); - REQUIRE_THAT(src, - IsInstantiation( - _A("Overload"), _A("Overload"))); - REQUIRE_THAT(src, - IsAggregation( - _A("R"), _A("Overload"), "+dispatch")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "AHandler", "A")); + REQUIRE(IsDependency(src, "BHandler", "B")); + REQUIRE(IsInstantiation( + src, "Overload", "Overload")); + REQUIRE(IsAggregation( + src, "R", "Overload", "dispatch")); + }); } \ No newline at end of file diff --git a/tests/t00074/test_case.h b/tests/t00074/test_case.h index 3409091c..3c18a396 100644 --- a/tests/t00074/test_case.h +++ b/tests/t00074/test_case.h @@ -16,76 +16,33 @@ * limitations under the License. */ -TEST_CASE("t00074", "[test-case][class]") +TEST_CASE("t00074") { - auto [config, db] = load_config("t00074"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00074_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00074", "t00074_class"); - REQUIRE(diagram->name == "t00074_class"); + CHECK_CLASS_DIAGRAM( + config, diagram, *model, + [](const auto &src) { + REQUIRE(IsConcept(src, "fruit_c")); + REQUIRE(IsConcept(src, "apple_c")); + REQUIRE(IsConcept(src, "orange_c")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00074_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsConcept(_A("fruit_c"))); - REQUIRE_THAT(src, IsConcept(_A("apple_c"))); - REQUIRE_THAT(src, IsConcept(_A("orange_c"))); - - REQUIRE_THAT( - src, IsConstraint(_A("apple_c"), _A("fruit_c"), "T")); - REQUIRE_THAT( - src, IsConstraint(_A("orange_c"), _A("fruit_c"), "T")); - - REQUIRE_THAT( - src, !IsConceptRequirement(_A("apple_c"), "t.get_sweetness()")); - REQUIRE_THAT(src, - !IsConceptRequirement(_A("orange_c"), "t.get_bitterness()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsConcept(j, "fruit_c")); - REQUIRE(IsConcept(j, "apple_c")); - REQUIRE(IsConcept(j, "orange_c")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsConcept; - using mermaid::IsConceptRequirement; - using mermaid::IsConstraint; - - REQUIRE_THAT(src, IsConcept(_A("fruit_c"))); - REQUIRE_THAT(src, IsConcept(_A("apple_c"))); - REQUIRE_THAT(src, IsConcept(_A("orange_c"))); - - REQUIRE_THAT( - src, IsConstraint(_A("apple_c"), _A("fruit_c"), "T")); - REQUIRE_THAT( - src, IsConstraint(_A("orange_c"), _A("fruit_c"), "T")); - - REQUIRE_THAT( - src, !IsConceptRequirement(_A("apple_c"), "t.get_sweetness()")); - REQUIRE_THAT( - src, !IsConceptRequirement(_A("apple_c"), "t.get_bitterness()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsConstraint(src, "apple_c", "fruit_c", "T")); + REQUIRE(IsConstraint(src, "orange_c", "fruit_c", "T")); + }, + [](const plantuml_t &src) { + REQUIRE( + !IsConceptRequirement(src, "apple_c", "t.get_sweetness()")); + REQUIRE(!IsConceptRequirement( + src, "orange_c", "t.get_bitterness()")); + }, + [](const mermaid_t &src) { + REQUIRE( + !IsConceptRequirement(src, "apple_c", "t.get_sweetness()")); + REQUIRE(!IsConceptRequirement( + src, "orange_c", "t.get_bitterness()")); + }); } \ No newline at end of file diff --git a/tests/t00075/test_case.h b/tests/t00075/test_case.h index e1f4ac19..7d551eb0 100644 --- a/tests/t00075/test_case.h +++ b/tests/t00075/test_case.h @@ -16,77 +16,29 @@ * limitations under the License. */ -TEST_CASE("t00075", "[test-case][class]") +TEST_CASE("t00075") { - auto [config, db] = load_config("t00075"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00075_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00075", "t00075_class"); - REQUIRE(diagram->name == "t00075_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, {"ns1::ns2", "A"})); + REQUIRE(IsClass(src, {"ns1::ns2", "B"})); + REQUIRE(IsClass(src, {"ns1::ns2", "ABE"})); + REQUIRE(IsClass(src, {"ns1::ns2", "R"})); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsEnum(src, {"ns1::ns2", "E"})); - REQUIRE(model->name() == "t00075_class"); + REQUIRE(IsConcept(src, {"ns1::ns2", "C"})); - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(IsConceptRequirement(src, "C", "T{}")); + REQUIRE(IsConceptRequirement(src, "C", "t.e()")); + REQUIRE(IsConceptParameterList(src, "C", "(T t)")); + REQUIRE(!IsConceptParameterList(src, "C", "(T ns1::ns2::t)")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("ABE"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsEnum(_A("E"))); - - REQUIRE_THAT(src, IsConcept(_A("C"))); - - REQUIRE_THAT(src, IsConceptRequirement(_A("C"), "T{}")); - REQUIRE_THAT(src, IsConceptRequirement(_A("C"), "t.e()")); - REQUIRE_THAT(src, IsConceptRequirement(_A("C"), "(T t)")); - REQUIRE_THAT(src, !IsConceptRequirement(_A("C"), "(T ns1::ns2::t)")); - - REQUIRE_THAT(src, - IsConstraint(_A("ABE"), _A("C"), "T", - "up[#green,dashed,thickness=2]")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - using mermaid::IsConcept; - using mermaid::IsConceptRequirement; - using mermaid::IsEnum; - - // Check if all classes exist - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::A"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::B"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::ABE"))); - REQUIRE_THAT(src, IsClass(_A("ns1::ns2::R"))); - - REQUIRE_THAT(src, IsEnum(_A("ns1::ns2::E"))); - - REQUIRE_THAT(src, IsConcept(_A("ns1::ns2::C"))); - - REQUIRE_THAT(src, IsConceptRequirement(_A("ns1::ns2::C"), "T{}")); - REQUIRE_THAT(src, IsConceptRequirement(_A("ns1::ns2::C"), "t.e()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsConstraint(src, {"ns1::ns2", "ABE"}, + {"ns1::ns2", "C"}, "T", "up[#green,dashed,thickness=2]")); + }); } \ No newline at end of file diff --git a/tests/t20001/test_case.h b/tests/t20001/test_case.h index f06f150d..818c55b9 100644 --- a/tests/t20001/test_case.h +++ b/tests/t20001/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t20001/test_case.cc + * tests/t20001/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,106 +16,62 @@ * limitations under the License. */ -TEST_CASE("t20001", "[test-case][sequence]") +TEST_CASE("t20001") { - auto [config, db] = load_config("t20001"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20001_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20001", "t20001_sequence"); - REQUIRE(diagram->name == "t20001_sequence"); + CHECK_SEQUENCE_DIAGRAM( + config, diagram, *model, + [](const auto &src) { + REQUIRE(HasTitle(src, "Basic sequence diagram example")); - auto model = generate_sequence_diagram(*db, diagram); + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "A()"}, // + {"tmain()", "B", "B(A &)"}, // - REQUIRE(model->name() == "t20001_sequence"); + {"tmain()", "A", "add(int,int)"}, // - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); + {"tmain()", "B", "wrap_add3(int,int,int)"}, // + {"B", "A", "add3(int,int,int)"}, // + {"A", "A", "add(int,int)"}, // + {"A", "A", "log_result(int)", Static{}}, // + {"B", "A", "log_result(int)", Static{}} // + })); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(!HasMessage(src, {"A", {"detail", "C"}, "add(int,int)"})); - REQUIRE_THAT(src, HasTitle("Basic sequence diagram example")); + REQUIRE(HasComment(src, "t20001 test diagram of type sequence")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "add3(int,int,int)")); - REQUIRE_THAT(src, HasCall(_A("A"), "add(int,int)")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("detail::C"), "add(int,int)")); - REQUIRE_THAT(src, HasCall(_A("A"), "__log_result(int)__")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "__log_result(int)__")); + REQUIRE(HasMessageComment(src, "tmain()", "Just add 2 numbers")); - REQUIRE_THAT(src, HasComment("t20001 test diagram of type sequence")); + REQUIRE(HasMessageComment(src, "tmain()", "And now add another 2")); + }, + [](const json_t &src) { + const auto &A = get_participant(src.src, "A"); - REQUIRE_THAT( - src, HasMessageComment(_A("tmain()"), "Just add 2 numbers")); + CHECK(A.has_value()); - REQUIRE_THAT( - src, HasMessageComment(_A("tmain()"), "And now add another 2")); + CHECK(A.value()["type"] == "class"); + CHECK(A.value()["name"] == "A"); + CHECK(A.value()["display_name"] == "A"); + CHECK(A.value()["namespace"] == "clanguml::t20001"); + CHECK(A.value()["source_location"]["file"] == "t20001.cc"); + CHECK(A.value()["source_location"]["line"] == 13); - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_sequence_json(diagram, *model); + const auto &tmain = get_participant(src.src, "tmain()"); - using namespace json; + CHECK(tmain.has_value()); - const auto &A = get_participant(j, "A"); - - CHECK(A.has_value()); - - CHECK(A.value()["type"] == "class"); - CHECK(A.value()["name"] == "A"); - CHECK(A.value()["display_name"] == "A"); - CHECK(A.value()["namespace"] == "clanguml::t20001"); - CHECK(A.value()["source_location"]["file"] == "t20001.cc"); - CHECK(A.value()["source_location"]["line"] == 13); - - const auto &tmain = get_participant(j, "tmain()"); - - CHECK(tmain.has_value()); - - CHECK(tmain.value()["type"] == "function"); - CHECK(tmain.value()["name"] == "tmain"); - CHECK(tmain.value()["display_name"] == "tmain()"); - CHECK(tmain.value()["namespace"] == "clanguml::t20001"); - CHECK(tmain.value()["source_location"]["file"] == "t20001.cc"); - CHECK(tmain.value()["source_location"]["line"] == 61); - - REQUIRE(HasTitle(j, "Basic sequence diagram example")); - - REQUIRE(IsFunctionParticipant(j, "tmain()")); - REQUIRE(IsClassParticipant(j, "A")); - REQUIRE(IsClassParticipant(j, "B")); - - std::vector messages = { - FindMessage(j, "tmain()", "A", "add(int,int)"), - FindMessage(j, "tmain()", "B", "wrap_add3(int,int,int)"), - FindMessage(j, "B", "A", "add3(int,int,int)"), - FindMessage(j, "A", "A", "add(int,int)"), - FindMessage(j, "A", "A", "log_result(int)"), - FindMessage(j, "B", "A", "log_result(int)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - using mermaid::HasComment; - using mermaid::HasTitle; - - REQUIRE_THAT(src, HasTitle("Basic sequence diagram example")); - - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "add3(int,int,int)")); - REQUIRE_THAT(src, HasCall(_A("A"), "add(int,int)")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("detail::C"), "add(int,int)")); - REQUIRE_THAT(src, HasCall(_A("A"), "log_result(int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "log_result(int)")); - - REQUIRE_THAT(src, HasComment("t20001 test diagram of type sequence")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK(tmain.value()["type"] == "function"); + CHECK(tmain.value()["name"] == "tmain"); + CHECK(tmain.value()["display_name"] == "tmain()"); + CHECK(tmain.value()["namespace"] == "clanguml::t20001"); + CHECK(tmain.value()["source_location"]["file"] == "t20001.cc"); + CHECK(tmain.value()["source_location"]["line"] == 61); + }); } diff --git a/tests/t20002/test_case.h b/tests/t20002/test_case.h index 65b08719..aecc06e9 100644 --- a/tests/t20002/test_case.h +++ b/tests/t20002/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t20002/test_case.cc + * tests/t20002/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,61 +16,25 @@ * limitations under the License. */ -TEST_CASE("t20002", "[test-case][sequence]") +TEST_CASE("t20002") { - auto [config, db] = load_config("t20002"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20002_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20002", "t20002_sequence"); - REQUIRE(diagram->name == "t20002_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsFunctionParticipant(src, "m1()")); + REQUIRE(IsFunctionParticipant(src, "m2()")); + REQUIRE(IsFunctionParticipant(src, "m3()")); + REQUIRE(IsFunctionParticipant(src, "m4()")); - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20002_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, HasCall(_A("m1()"), _A("m2()"), "")); - REQUIRE_THAT(src, HasCall(_A("m2()"), _A("m3()"), "")); - REQUIRE_THAT(src, HasCall(_A("m3()"), _A("m4()"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - REQUIRE(IsFunctionParticipant(j, "m1()")); - REQUIRE(IsFunctionParticipant(j, "m2()")); - REQUIRE(IsFunctionParticipant(j, "m3()")); - REQUIRE(IsFunctionParticipant(j, "m4()")); - - std::vector messages = {FindMessage(j, "m1()", "m2()", ""), - FindMessage(j, "m2()", "m3()", ""), - FindMessage(j, "m3()", "m4()", "")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("m1()"), _A("m2()"), "")); - REQUIRE_THAT(src, HasCall(_A("m2()"), _A("m3()"), "")); - REQUIRE_THAT(src, HasCall(_A("m3()"), _A("m4()"), "")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(MessageOrder(src, + { + // + {"m1()", "m2()", ""}, // + {"m2()", "m3()", ""}, // + {"m3()", "m4()", ""} // + })); + }); } diff --git a/tests/t20003/test_case.h b/tests/t20003/test_case.h index 6d8fbe3c..ba5c844e 100644 --- a/tests/t20003/test_case.h +++ b/tests/t20003/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t20003/test_case.cc + * tests/t20003/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,56 +16,25 @@ * limitations under the License. */ -TEST_CASE("t20003", "[test-case][sequence]") +TEST_CASE("t20003") { - auto [config, db] = load_config("t20003"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20003_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20003", "t20003_sequence"); - REQUIRE(diagram->name == "t20003_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsFunctionTemplateParticipant(src, "m1(T)")); + REQUIRE(IsFunctionTemplateParticipant(src, "m2(T)")); + REQUIRE(IsFunctionTemplateParticipant(src, "m3(T)")); + REQUIRE(IsFunctionTemplateParticipant(src, "m4(T)")); - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20003_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, HasCall(_A("m1(T)"), _A("m2(T)"), "")); - REQUIRE_THAT(src, HasCall(_A("m2(T)"), _A("m3(T)"), "")); - REQUIRE_THAT(src, HasCall(_A("m3(T)"), _A("m4(T)"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = {FindMessage(j, "m1(T)", "m2(T)", ""), - FindMessage(j, "m2(T)", "m3(T)", ""), - FindMessage(j, "m3(T)", "m4(T)", "")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("m1(T)"), _A("m2(T)"), "")); - REQUIRE_THAT(src, HasCall(_A("m2(T)"), _A("m3(T)"), "")); - REQUIRE_THAT(src, HasCall(_A("m3(T)"), _A("m4(T)"), "")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(MessageOrder(src, + { + // + {"m1(T)", "m2(T)", ""}, // + {"m2(T)", "m3(T)", ""}, // + {"m3(T)", "m4(T)", ""} // + })); + }); } diff --git a/tests/t20004/test_case.h b/tests/t20004/test_case.h index 67b37ed9..b576a878 100644 --- a/tests/t20004/test_case.h +++ b/tests/t20004/test_case.h @@ -16,102 +16,30 @@ * limitations under the License. */ -TEST_CASE("t20004", "[test-case][sequence]") +TEST_CASE("t20004") { - auto [config, db] = load_config("t20004"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20004_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20004", "t20004_sequence"); - REQUIRE(diagram->name == "t20004_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"main()", "m1(float)", ""}, // + {"main()", "m1(unsigned long)", ""}, // + {"m1(unsigned long)", + "m4(unsigned long)", ""}, // + {"main()", "m1(std::string)", ""}, // + {"m1(std::string)", "m2(std::string)", + ""}, // + {"main()", "m1(int)", ""}, // + {"m1(int)", "m2(int)", ""}, // + {"m2(int)", "m3(int)", ""}, // + {"m3(int)", "m4(int)", ""} // + })); - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20004_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, HasCall(_A("main()"), _A("m1(float)"), "")); - REQUIRE_THAT( - src, !HasCall(_A("m1(float)"), _A("m1(float)"), "")); - REQUIRE_THAT( - src, !HasCall(_A("m1(float)"), _A("m1(float)"), "")); - - REQUIRE_THAT(src, - HasCall(_A("main()"), _A("m1(unsigned long)"), "")); - REQUIRE_THAT(src, - HasCall(_A("m1(unsigned long)"), - _A("m4(unsigned long)"), "")); - - REQUIRE_THAT( - src, HasCall(_A("main()"), _A("m1(std::string)"), "")); - REQUIRE_THAT(src, - HasCall(_A("m1(std::string)"), - _A("m2(std::string)"), "")); - - REQUIRE_THAT(src, HasCall(_A("main()"), _A("m1(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("m1(int)"), _A("m2(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("m2(int)"), _A("m3(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("m3(int)"), _A("m4(int)"), "")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "main()", "m1(float)", ""), - FindMessage(j, "main()", "m1(unsigned long)", ""), - FindMessage(j, "m1(unsigned long)", - "m4(unsigned long)", ""), - FindMessage(j, "main()", "m1(std::string)", ""), - FindMessage(j, "m1(std::string)", - "m2(std::string)", ""), - FindMessage(j, "main()", "m1(int)", ""), - FindMessage(j, "m1(int)", "m2(int)", ""), - FindMessage(j, "m2(int)", "m3(int)", ""), - FindMessage(j, "m3(int)", "m4(int)", "")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("main()"), _A("m1(float)"), "")); - REQUIRE_THAT( - src, !HasCall(_A("m1(float)"), _A("m1(float)"), "")); - REQUIRE_THAT( - src, !HasCall(_A("m1(float)"), _A("m1(float)"), "")); - - REQUIRE_THAT(src, - HasCall(_A("main()"), _A("m1(unsigned long)"), "")); - REQUIRE_THAT(src, - HasCall(_A("m1(unsigned long)"), - _A("m4(unsigned long)"), "")); - - REQUIRE_THAT( - src, HasCall(_A("main()"), _A("m1(std::string)"), "")); - REQUIRE_THAT(src, - HasCall(_A("m1(std::string)"), - _A("m2(std::string)"), "")); - - REQUIRE_THAT(src, HasCall(_A("main()"), _A("m1(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("m1(int)"), _A("m2(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("m2(int)"), _A("m3(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("m3(int)"), _A("m4(int)"), "")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!HasMessage(src, {"m1(float)", "m1(float)", ""})); + }); } \ No newline at end of file diff --git a/tests/t20005/test_case.h b/tests/t20005/test_case.h index 330bbdb1..672b0444 100644 --- a/tests/t20005/test_case.h +++ b/tests/t20005/test_case.h @@ -16,60 +16,21 @@ * limitations under the License. */ -TEST_CASE("t20005", "[test-case][sequence]") +TEST_CASE("t20005") { - auto [config, db] = load_config("t20005"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20005_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20005", "t20005_sequence"); - REQUIRE(diagram->name == "t20005_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20005_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasEntrypoint(_A("C"), "c(T)")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b(T)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a(T)")); - REQUIRE_THAT(src, HasExitpoint(_A("C"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = {FindMessage(j, "C", "B", "b(T)"), - FindMessage(j, "B", "A", "a(T)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - using mermaid::HasEntrypoint; - using mermaid::HasExitpoint; - - REQUIRE_THAT(src, HasEntrypoint(_A("C"), "c(T)")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b(T)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a(T)")); - REQUIRE_THAT(src, HasExitpoint(_A("C"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {Entrypoint{}, "C", "c(T)"}, // + {"C", "B", "b(T)"}, // + {"B", "A", "a(T)"}, // + {Exitpoint{}, "C"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20006/test_case.h b/tests/t20006/test_case.h index c825244f..d643b4c0 100644 --- a/tests/t20006/test_case.h +++ b/tests/t20006/test_case.h @@ -16,132 +16,33 @@ * limitations under the License. */ -TEST_CASE("t20006", "[test-case][sequence]") +TEST_CASE("t20006") { - auto [config, db] = load_config("t20006"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20006_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20006", "t20006_sequence"); - REQUIRE(diagram->name == "t20006_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "B", "b(int)"}, // + {"B", "A", "a1(int)"}, // + {"tmain()", "B", "b(std::string)"}, // + {"B", "A", "a2(std::string)"}, // + {"tmain()", "BB", "bb1(int,int)"}, // + {"BB", "AA", "aa1(int)"}, // + {"tmain()", "BB", "bb2(int,int)"}, // + {"BB", "AA", "aa2(int)"}, // + {"tmain()", "BB", "bb1(int,std::string)"}, // + {"BB", "AA", "aa2(int)"}, // + {"tmain()", "BB", "bb2(int,std::string)"}, // + {"BB", "AA", "aa1(int)"}, // + {"tmain()", "BB", "bb1(int,float)"}, // + {"BB", "BB", "bb2(int,float)"}, // + {"BB", "AA", "aa2(int)"} // - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20006_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b(int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int)")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("B"), "b(std::string)")); - REQUIRE_THAT(src, - HasCall( - _A("B"), _A("A"), "a2(std::string)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain()"), _A("BB"), "bb1(int,int)")); - REQUIRE_THAT( - src, HasCall(_A("BB"), _A("AA"), "aa1(int)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain()"), _A("BB"), "bb2(int,int)")); - REQUIRE_THAT( - src, HasCall(_A("BB"), _A("AA"), "aa2(int)")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("BB"), - "bb1(int,std::string)")); - REQUIRE_THAT( - src, HasCall(_A("BB"), _A("AA"), "aa2(int)")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("BB"), - "bb2(int,std::string)")); - REQUIRE_THAT( - src, HasCall(_A("BB"), _A("AA"), "aa1(int)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain()"), _A("BB"), "bb1(int,float)")); - REQUIRE_THAT(src, - HasCall( - _A("BB"), _A("BB"), "bb2(int,float)")); - REQUIRE_THAT( - src, HasCall(_A("BB"), _A("AA"), "aa2(int)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "B", "b(int)"), - FindMessage(j, "B", "A", "a1(int)"), - FindMessage(j, "tmain()", "B", "b(std::string)"), - FindMessage(j, "tmain()", "BB", "bb1(int,int)"), - FindMessage(j, "BB", "AA", "aa1(int)"), - FindMessage( - j, "tmain()", "BB", "bb1(int,std::string)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b(int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int)")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("B"), "b(std::string)")); - REQUIRE_THAT(src, - HasCall( - _A("B"), _A("A"), "a2(std::string)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain()"), _A("BB"), "bb1(int,int)")); - REQUIRE_THAT( - src, HasCall(_A("BB"), _A("AA"), "aa1(int)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain()"), _A("BB"), "bb2(int,int)")); - REQUIRE_THAT( - src, HasCall(_A("BB"), _A("AA"), "aa2(int)")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("BB"), - "bb1(int,std::string)")); - REQUIRE_THAT( - src, HasCall(_A("BB"), _A("AA"), "aa2(int)")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("BB"), - "bb2(int,std::string)")); - REQUIRE_THAT( - src, HasCall(_A("BB"), _A("AA"), "aa1(int)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain()"), _A("BB"), "bb1(int,float)")); - REQUIRE_THAT(src, - HasCall( - _A("BB"), _A("BB"), "bb2(int,float)")); - REQUIRE_THAT( - src, HasCall(_A("BB"), _A("AA"), "aa2(int)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + })); + }); } \ No newline at end of file diff --git a/tests/t20007/test_case.h b/tests/t20007/test_case.h index 97cfa231..ada4af73 100644 --- a/tests/t20007/test_case.h +++ b/tests/t20007/test_case.h @@ -16,73 +16,21 @@ * limitations under the License. */ -TEST_CASE("t20007", "[test-case][sequence]") +TEST_CASE("t20007") { - auto [config, db] = load_config("t20007"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20007_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20007", "t20007_sequence"); - REQUIRE(diagram->name == "t20007_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20007_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("Adder"), "add(int &&,int &&)")); - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("Adder"), - "add(int &&,float &&,double &&)")); - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("Adder"), - "add(std::string &&,std::string &&,std::string &&)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "Adder", "add(int &&,int &&)"), - FindMessage(j, "tmain()", "Adder", - "add(int &&,float &&,double &&)"), - FindMessage(j, "tmain()", - "Adder", - "add(std::string &&,std::string &&,std::string &&)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("Adder"), "add(int &&,int &&)")); - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("Adder"), - "add(int &&,float &&,double &&)")); - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("Adder"), - "add(std::string &&,std::string &&,std::string &&)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + {"tmain()", "Adder", "add(int &&,int &&)"}, // + {"tmain()", "Adder", + "add(int &&,float &&,double &&)"}, // + {"tmain()", "Adder", + "add(std::string &&,std::string &&,std::string &&)"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20008/test_case.h b/tests/t20008/test_case.h index 0a98e6fd..3d0d5c20 100644 --- a/tests/t20008/test_case.h +++ b/tests/t20008/test_case.h @@ -16,91 +16,28 @@ * limitations under the License. */ -TEST_CASE("t20008", "[test-case][sequence]") +TEST_CASE("t20008") { - auto [config, db] = load_config("t20008"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20008_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20008", "t20008_sequence"); - REQUIRE(diagram->name == "t20008_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "B", "b(int)"}, // + {"B", "A", "a1(int)"}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain()", "B", "b(const char *)"}, // + {"B", "A", "a2(const char *)"}, // - REQUIRE(model->name() == "t20008_sequence"); + {"tmain()", "B", "b(std::string)"}, // + {"B", "A", "a3(std::string)"} // + })); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b(int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int)")); - // REQUIRE_THAT(puml, !HasCall(_A("B"), _A("A"), - // "a2(int)")); REQUIRE_THAT(puml, !HasCall(_A("B"), - // _A("A"), "a3(int)")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("B"), "b(const char *)")); - REQUIRE_THAT(src, - HasCall(_A("B"), _A("A"), - "a2(const char *)")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("B"), "b(std::string)")); - REQUIRE_THAT(src, - HasCall( - _A("B"), _A("A"), "a3(std::string)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "B", "b(int)"), - FindMessage(j, "B", "A", "a1(int)"), - FindMessage(j, "tmain()", "B", "b(const char *)"), - FindMessage( - j, "B", "A", "a2(const char *)"), - FindMessage(j, "tmain()", "B", "b(std::string)"), - FindMessage( - j, "B", "A", "a3(std::string)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b(int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int)")); - // REQUIRE_THAT(puml, !HasCall(_A("B"), _A("A"), - // "a2(int)")); REQUIRE_THAT(puml, !HasCall(_A("B"), - // _A("A"), "a3(int)")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("B"), "b(const char *)")); - REQUIRE_THAT(src, - HasCall(_A("B"), _A("A"), - "a2(const char *)")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("B"), "b(std::string)")); - REQUIRE_THAT(src, - HasCall( - _A("B"), _A("A"), "a3(std::string)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!HasMessage(src, {"B", "A", "a2(int)"})); + REQUIRE(!HasMessage(src, {"B", "A", "a3(int)"})); + }); } \ No newline at end of file diff --git a/tests/t20009/test_case.h b/tests/t20009/test_case.h index 64bc4235..4388615b 100644 --- a/tests/t20009/test_case.h +++ b/tests/t20009/test_case.h @@ -16,78 +16,25 @@ * limitations under the License. */ -TEST_CASE("t20009", "[test-case][sequence]") +TEST_CASE("t20009") { - auto [config, db] = load_config("t20009"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20009_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20009", "t20009_sequence"); - REQUIRE(diagram->name == "t20009_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "B", "b(std::string)"}, // + {"B", "A", "a(std::string)"}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain()", "B", "b(int)"}, // + {"B", "A", "a(int)"}, // - REQUIRE(model->name() == "t20009_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("B"), "b(std::string)")); - REQUIRE_THAT(src, - HasCall( - _A("B"), _A("A"), "a(std::string)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b(int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a(int)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b(float)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a(float)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "B", "b(std::string)"), - FindMessage( - j, "B", "A", "a(std::string)"), - FindMessage(j, "tmain()", "B", "b(int)"), - FindMessage(j, "B", "A", "a(int)"), - FindMessage(j, "tmain()", "B", "b(float)"), - FindMessage(j, "B", "A", "a(float)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("B"), "b(std::string)")); - REQUIRE_THAT(src, - HasCall( - _A("B"), _A("A"), "a(std::string)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b(int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a(int)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b(float)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a(float)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "B", "b(float)"}, // + {"B", "A", "a(float)"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20010/test_case.h b/tests/t20010/test_case.h index a4e0f76c..274a88ff 100644 --- a/tests/t20010/test_case.h +++ b/tests/t20010/test_case.h @@ -16,79 +16,27 @@ * limitations under the License. */ -TEST_CASE("t20010", "[test-case][sequence]") +TEST_CASE("t20010") { - auto [config, db] = load_config("t20010"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20010_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20010", "t20010_sequence"); - REQUIRE(diagram->name == "t20010_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + {"tmain()", "B", "b1()"}, // + {"B", "A", "a1()"}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain()", "B", "b2()"}, // + {"B", "A", "a2()"}, // - REQUIRE(model->name() == "t20010_sequence"); + {"tmain()", "B", "b3()"}, // + {"B", "A", "a3()"}, // - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b1()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b2()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b3()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a3()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b4()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a4()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "B", "b1()"), - FindMessage(j, "B", "A", "a1()"), - FindMessage(j, "tmain()", "B", "b2()"), - FindMessage(j, "B", "A", "a2()"), - FindMessage(j, "tmain()", "B", "b3()"), - FindMessage(j, "B", "A", "a3()"), - FindMessage(j, "tmain()", "B", "b4()"), - FindMessage(j, "B", "A", "a4()")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b1()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b2()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b3()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a3()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b4()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a4()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "B", "b4()"}, // + {"B", "A", "a4()"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20011/test_case.h b/tests/t20011/test_case.h index e6f4b81a..b9ba1828 100644 --- a/tests/t20011/test_case.h +++ b/tests/t20011/test_case.h @@ -16,68 +16,24 @@ * limitations under the License. */ -TEST_CASE("t20011", "[test-case][sequence]") +TEST_CASE("t20011") { - auto [config, db] = load_config("t20011"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20011_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20011", "t20011_sequence"); - REQUIRE(diagram->name == "t20011_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "a(int)"}, // + {"A", "A", "a(int)"}, // - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20011_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a(int)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "b(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "c(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "d(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "b(int)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - REQUIRE(IsFunctionParticipant(j, "tmain()")); - REQUIRE(IsClassParticipant(j, "A")); - - std::vector messages = {FindMessage(j, "tmain()", "A", "a(int)"), - FindMessage(j, "A", "A", "a(int)"), - FindMessage(j, "tmain()", "A", "b(int)"), - FindMessage(j, "A", "A", "c(int)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a(int)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "b(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "c(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "d(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "b(int)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "A", "b(int)"}, // + {"A", "A", "c(int)"}, // + {"A", "A", "d(int)"}, // + {"A", "A", "b(int)"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20012/test_case.h b/tests/t20012/test_case.h index 918a7d96..2327889d 100644 --- a/tests/t20012/test_case.h +++ b/tests/t20012/test_case.h @@ -16,143 +16,56 @@ * limitations under the License. */ -TEST_CASE("t20012", "[test-case][sequence]") +TEST_CASE("t20012") { - auto [config, db] = load_config("t20012"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20012_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20012", "t20012_sequence"); - REQUIRE(diagram->name == "t20012_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + {"tmain()", "tmain()::(lambda t20012.cc:67:20)", + "operator()() const"}, // + {"tmain()::(lambda t20012.cc:67:20)", "A", "a()"}, // + {"A", "A", "aa()"}, // + {"A", "A", "aaa()"}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain()::(lambda t20012.cc:67:20)", "B", "b()"}, // + {"B", "B", "bb()"}, // + {"B", "B", "bbb()"}, // - REQUIRE(model->name() == "t20012_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); + {"tmain()", "tmain()::(lambda t20012.cc:80:20)", + "operator()() const"}, // + {"tmain()::(lambda t20012.cc:80:20)", "C", "c()"}, // + {"C", "C", "cc()"}, // + {"C", "C", "ccc()"}, // - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + {"tmain()::(lambda t20012.cc:80:20)", + "tmain()::(lambda t20012.cc:67:20)", + "operator()() const"}, // - // Check if all calls exist - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("tmain()::(lambda t20012.cc:67:20)"), - "operator()() const")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:67:20)"), _A("A"), "a()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "aa()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "aaa()")); + {"tmain()::(lambda t20012.cc:67:20)", "A", "a()"}, // - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:67:20)"), _A("B"), "b()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "bb()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "bbb()")); + {"A", "A", "aa()"}, // + {"A", "A", "aaa()"}, // - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:80:20)"), _A("C"), "c()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "cc()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "ccc()")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:80:20)"), - _A("tmain()::(lambda t20012.cc:67:20)"), "operator()() const")); + {"tmain()::(lambda t20012.cc:67:20)", "B", "b()"}, // + {"B", "B", "bb()"}, // + {"B", "B", "bbb()"}, // - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "ccc()")); + {"tmain()", "R<(lambda at t20012.cc:86:9)>", + "R((lambda at t20012.cc:86:9) &&)"}, // + {"tmain()", "R<(lambda at t20012.cc:86:9)>", "r()"}, // + {"R<(lambda at t20012.cc:86:9)>", + "tmain()::(lambda t20012.cc:86:9)", + "operator()() const"}, // + {"tmain()::(lambda t20012.cc:86:9)", "C", "c()"}, // - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("R<(lambda at t20012.cc:86:9)>"), - "R((lambda at t20012.cc:86:9) &&)")); - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("R<(lambda at t20012.cc:86:9)>"), "r()")); - REQUIRE_THAT(src, - HasCall(_A("R<(lambda at t20012.cc:86:9)>"), - _A("tmain()::(lambda t20012.cc:86:9)"), "operator()() const")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:86:9)"), _A("C"), "c()")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("tmain()::(lambda t20012.cc:94:9)"), - "operator()(auto) const")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:94:9)"), _A("D"), - "add5(int) const")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "tmain()::(lambda t20012.cc:67:20)", - "operator()() const"), - FindMessage(j, "tmain()::(lambda t20012.cc:67:20)", "A", "a()"), - FindMessage(j, "A", "A", "aa()"), - FindMessage(j, "A", "A", "aaa()"), - FindMessage(j, "tmain()::(lambda t20012.cc:67:20)", "B", "b()"), - FindMessage(j, "B", "B", "bb()"), - FindMessage(j, "B", "B", "bbb()"), - FindMessage(j, "tmain()::(lambda t20012.cc:80:20)", "C", "c()"), - FindMessage(j, "C", "C", "cc()"), - FindMessage(j, "C", "C", "ccc()"), - FindMessage(j, "tmain()::(lambda t20012.cc:80:20)", - "tmain()::(lambda t20012.cc:67:20)", "operator()() const"), - FindMessage(j, "tmain()", "R<(lambda at t20012.cc:86:9)>", "r()"), - FindMessage(j, "R<(lambda at t20012.cc:86:9)>", - "tmain()::(lambda t20012.cc:86:9)", "operator()() const"), - FindMessage(j, "tmain()::(lambda t20012.cc:86:9)", "C", "c()"), - }; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("tmain()::(lambda t20012.cc:67:20)"), - "operator()() const")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:67:20)"), _A("A"), "a()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "aa()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "aaa()")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:67:20)"), _A("B"), "b()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "bb()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "bbb()")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:80:20)"), _A("C"), "c()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "cc()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "ccc()")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:80:20)"), - _A("tmain()::(lambda t20012.cc:67:20)"), "operator()() const")); - - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "ccc()")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("R<(lambda at t20012.cc:86:9)>"), "r()")); - REQUIRE_THAT(src, - HasCall(_A("R<(lambda at t20012.cc:86:9)>"), - _A("tmain()::(lambda t20012.cc:86:9)"), "operator()() const")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:86:9)"), _A("C"), "c()")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("tmain()::(lambda t20012.cc:94:9)"), - "operator()(auto) const")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20012.cc:94:9)"), _A("D"), - "add5(int) const")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "tmain()::(lambda t20012.cc:94:9)", + "operator()(auto) const"}, // + {"tmain()::(lambda t20012.cc:94:9)", "D", "add5(int) const"} // + })); + }); } diff --git a/tests/t20013/test_case.h b/tests/t20013/test_case.h index 733f7e20..7dad2a28 100644 --- a/tests/t20013/test_case.h +++ b/tests/t20013/test_case.h @@ -16,74 +16,25 @@ * limitations under the License. */ -TEST_CASE("t20013", "[test-case][sequence]") +TEST_CASE("t20013") { - auto [config, db] = load_config("t20013"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20013_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20013", "t20013_sequence"); - REQUIRE(diagram->name == "t20013_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain(int,char **)", "B", "b(int)"}, // + {"B", "A", "a1(int)"}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain(int,char **)", "B", "b(double)"}, // + {"B", "A", "a2(double)"}, // - REQUIRE(model->name() == "t20013_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(double)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2(double)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(const char *)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a3(const char *)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain(int,char **)", "B", "b(int)"), - FindMessage(j, "B", "A", "a1(int)"), - FindMessage(j, "tmain(int,char **)", "B", "b(double)"), - FindMessage(j, "B", "A", "a2(double)"), - FindMessage(j, "tmain(int,char **)", "B", "b(const char *)"), - FindMessage(j, "B", "A", "a3(const char *)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(double)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2(double)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(const char *)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a3(const char *)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain(int,char **)", "B", "b(const char *)"}, // + {"B", "A", "a3(const char *)"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20014/test_case.h b/tests/t20014/test_case.h index 8bb84bbc..43f54e5a 100644 --- a/tests/t20014/test_case.h +++ b/tests/t20014/test_case.h @@ -16,72 +16,25 @@ * limitations under the License. */ -TEST_CASE("t20014", "[test-case][sequence]") +TEST_CASE("t20014") { - auto [config, db] = load_config("t20014"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20014_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20014", "t20014_sequence"); - REQUIRE(diagram->name == "t20014_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "B", "b1(int,int)"}, // + {"B", "A", "a1(int,int)"}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain()", "B", "b2(int,int)"}, // + {"B", "A", "a2(int,int)"}, // - REQUIRE(model->name() == "t20014_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b1(int,int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int,int)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b2(int,int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2(int,int)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain()"), _A("C"), "c1(int,int)")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b1(int,int)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "B", "b1(int,int)"), - FindMessage(j, "B", "A", "a1(int,int)"), - FindMessage(j, "tmain()", "B", "b2(int,int)"), - FindMessage(j, "B", "A", "a2(int,int)"), - FindMessage(j, "tmain()", "C", "c1(int,int)"), - FindMessage(j, "C", "B", "b1(int,int)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b1(int,int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int,int)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b2(int,int)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2(int,int)")); - - REQUIRE_THAT( - src, HasCall(_A("tmain()"), _A("C"), "c1(int,int)")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b1(int,int)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "C", "c1(int,int)"}, // + {"C", "B", "b1(int,int)"}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20015/test_case.h b/tests/t20015/test_case.h index 259cafb7..98ad91e1 100644 --- a/tests/t20015/test_case.h +++ b/tests/t20015/test_case.h @@ -16,69 +16,25 @@ * limitations under the License. */ -TEST_CASE("t20015", "[test-case][sequence]") +TEST_CASE("t20015") { - auto [config, db] = load_config("t20015"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20015_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20015", "t20015_sequence"); - REQUIRE(diagram->name == "t20015_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + {"tmain()", "B", "setup_a(std::shared_ptr &)"} // + })); - auto model = generate_sequence_diagram(*db, diagram); + REQUIRE(!HasMessage(src, {"B", {"detail", "A"}, "set_x(int)"})); + REQUIRE(!HasMessage(src, {"B", {"detail", "A"}, "set_y(int)"})); + REQUIRE(!HasMessage(src, {"B", {"detail", "A"}, "set_z(int)"})); - REQUIRE(model->name() == "t20015_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("B"), - "setup_a(std::shared_ptr &)")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("detail::A"), "set_x(int)")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("detail::A"), "set_y(int)")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("detail::A"), "set_z(int)")); - - REQUIRE_THAT(src, !HasCall(_A("B"), _A("B"), "set_x(int)")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("B"), "set_y(int)")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("B"), "set_z(int)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = {FindMessage( - j, "tmain()", "B", "setup_a(std::shared_ptr &)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("B"), - "setup_a(std::shared_ptr &)")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("detail::A"), "set_x(int)")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("detail::A"), "set_y(int)")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("detail::A"), "set_z(int)")); - - REQUIRE_THAT(src, !HasCall(_A("B"), _A("B"), "set_x(int)")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("B"), "set_y(int)")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("B"), "set_z(int)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!HasMessage(src, {"B", "B", "set_x(int)"})); + REQUIRE(!HasMessage(src, {"B", "B", "set_y(int)"})); + REQUIRE(!HasMessage(src, {"B", "B", "set_z(int)"})); + }); } \ No newline at end of file diff --git a/tests/t20016/test_case.h b/tests/t20016/test_case.h index b9bf1d12..df0e4c06 100644 --- a/tests/t20016/test_case.h +++ b/tests/t20016/test_case.h @@ -16,62 +16,21 @@ * limitations under the License. */ -TEST_CASE("t20016", "[test-case][sequence]") +TEST_CASE("t20016") { - auto [config, db] = load_config("t20016"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20016_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20016", "t20016_sequence"); - REQUIRE(diagram->name == "t20016_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20016_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b1(long)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b2(long)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2(const long &)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "B", "b1(long)"), - FindMessage(j, "B", "A", "a1(int)"), - FindMessage(j, "tmain()", "B", "b2(long)"), - FindMessage(j, "B", "A", "a2(const long &)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b1(long)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b2(long)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2(const long &)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "B", "b1(long)"}, // + {"B", "A", "a1(int)"}, // + {"tmain()", "B", "b2(long)"}, // + {"B", "A", "a2(const long &)"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20017/test_case.h b/tests/t20017/test_case.h index 37519ce6..30cc8778 100644 --- a/tests/t20017/test_case.h +++ b/tests/t20017/test_case.h @@ -16,94 +16,24 @@ * limitations under the License. */ -TEST_CASE("t20017", "[test-case][sequence]") +TEST_CASE("t20017") { - auto [config, db] = load_config("t20017"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20017_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20017", "t20017_sequence"); - REQUIRE(diagram->name == "t20017_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20017_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasEntrypoint(_A("t20017.cc"), "tmain()")); - REQUIRE_THAT(src, - HasCall(_A("t20017.cc"), _A("include/t20017_a.h"), "a1(int,int)")); - REQUIRE_THAT(src, - HasCall(_A("t20017.cc"), _A("include/t20017_a.h"), "a2(int,int)")); - REQUIRE_THAT(src, - HasCall(_A("t20017.cc"), _A("include/t20017_a.h"), "a3(int,int)")); - REQUIRE_THAT(src, - HasCall(_A("t20017.cc"), _A("include/t20017_b.h"), "b1(int,int)")); - REQUIRE_THAT(src, - HasCall( - _A("t20017.cc"), _A("include/t20017_b.h"), "b2(int,int)")); - REQUIRE_THAT(src, HasExitpoint(_A("t20017.cc"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - const auto &t20017_cc = get_participant(j, "t20017.cc"); - - CHECK(t20017_cc.has_value()); - - CHECK(t20017_cc.value()["type"] == "file"); - CHECK(t20017_cc.value()["name"] == "t20017.cc"); - CHECK(t20017_cc.value()["display_name"] == "t20017.cc"); - - std::vector messages = { - FindMessage(j, File("t20017.cc"), File("include/t20017_a.h"), - "a3(int,int)"), - FindMessage(j, File("t20017.cc"), File("include/t20017_b.h"), - "b1(int,int)"), - FindMessage(j, File("t20017.cc"), File("include/t20017_a.h"), - "a2(int,int)"), - FindMessage(j, File("t20017.cc"), File("include/t20017_a.h"), - "a1(int,int)"), - FindMessage(j, File("t20017.cc"), File("include/t20017_b.h"), - "b2(int,int)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - using mermaid::HasEntrypoint; - using mermaid::HasExitpoint; - - REQUIRE_THAT(src, HasEntrypoint(_A("t20017.cc"), "tmain()")); - REQUIRE_THAT(src, - HasCall(_A("t20017.cc"), _A("include/t20017_a.h"), "a1(int,int)")); - REQUIRE_THAT(src, - HasCall(_A("t20017.cc"), _A("include/t20017_a.h"), "a2(int,int)")); - REQUIRE_THAT(src, - HasCall(_A("t20017.cc"), _A("include/t20017_a.h"), "a3(int,int)")); - REQUIRE_THAT(src, - HasCall(_A("t20017.cc"), _A("include/t20017_b.h"), "b1(int,int)")); - REQUIRE_THAT(src, - HasCall( - _A("t20017.cc"), _A("include/t20017_b.h"), "b2(int,int)")); - REQUIRE_THAT(src, HasExitpoint(_A("t20017.cc"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {Entrypoint{}, "t20017.cc", "tmain()"}, // + {"t20017.cc", "include/t20017_a.h", "a3(int,int)"}, // + {"t20017.cc", "include/t20017_b.h", "b1(int,int)"}, // + {"t20017.cc", "include/t20017_a.h", "a2(int,int)"}, // + {"t20017.cc", "include/t20017_a.h", "a1(int,int)"}, // + {"t20017.cc", "include/t20017_b.h", "b2(int,int)"}, // + {Exitpoint{}, "t20017.cc"}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20018/test_case.h b/tests/t20018/test_case.h index ae618cae..5f99216a 100644 --- a/tests/t20018/test_case.h +++ b/tests/t20018/test_case.h @@ -16,88 +16,25 @@ * limitations under the License. */ -TEST_CASE("t20018", "[test-case][sequence]") +TEST_CASE("t20018") { - auto [config, db] = load_config("t20018"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20018_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20018", "t20018_sequence"); - REQUIRE(diagram->name == "t20018_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20018_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, - HasCall( - _A("tmain()"), _A("Answer,120>"), "__print()__")); - REQUIRE_THAT(src, - HasCall(_A("Answer,120>"), _A("Factorial<5>"), - "__print(int)__")); - REQUIRE_THAT(src, - HasCall(_A("Factorial<5>"), _A("Factorial<4>"), "__print(int)__")); - REQUIRE_THAT(src, - HasCall(_A("Factorial<4>"), _A("Factorial<3>"), "__print(int)__")); - REQUIRE_THAT(src, - HasCall(_A("Factorial<3>"), _A("Factorial<2>"), "__print(int)__")); - REQUIRE_THAT(src, - HasCall(_A("Factorial<2>"), _A("Factorial<1>"), "__print(int)__")); - REQUIRE_THAT(src, - HasCall(_A("Factorial<1>"), _A("Factorial<0>"), "__print(int)__")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "Answer,120>", "print()"), - FindMessage( - j, "Answer,120>", "Factorial<5>", "print(int)"), - FindMessage(j, "Factorial<5>", "Factorial<4>", "print(int)"), - FindMessage(j, "Factorial<4>", "Factorial<3>", "print(int)"), - FindMessage(j, "Factorial<3>", "Factorial<2>", "print(int)"), - FindMessage(j, "Factorial<2>", "Factorial<1>", "print(int)"), - FindMessage(j, "Factorial<1>", "Factorial<0>", "print(int)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("Answer,120>"), "print()")); - REQUIRE_THAT(src, - HasCall(_A("Answer,120>"), _A("Factorial<5>"), - "print(int)")); - REQUIRE_THAT( - src, HasCall(_A("Factorial<5>"), _A("Factorial<4>"), "print(int)")); - REQUIRE_THAT( - src, HasCall(_A("Factorial<4>"), _A("Factorial<3>"), "print(int)")); - REQUIRE_THAT( - src, HasCall(_A("Factorial<3>"), _A("Factorial<2>"), "print(int)")); - REQUIRE_THAT( - src, HasCall(_A("Factorial<2>"), _A("Factorial<1>"), "print(int)")); - REQUIRE_THAT( - src, HasCall(_A("Factorial<1>"), _A("Factorial<0>"), "print(int)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "Answer,120>", "print()", Static{}}, // + {"Answer,120>", "Factorial<5>", "print(int)", + Static{}}, // + {"Factorial<5>", "Factorial<4>", "print(int)", Static{}}, // + {"Factorial<4>", "Factorial<3>", "print(int)", Static{}}, // + {"Factorial<3>", "Factorial<2>", "print(int)", Static{}}, // + {"Factorial<2>", "Factorial<1>", "print(int)", Static{}}, // + {"Factorial<1>", "Factorial<0>", "print(int)", Static{}}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20019/test_case.h b/tests/t20019/test_case.h index 195655ff..e2ef00da 100644 --- a/tests/t20019/test_case.h +++ b/tests/t20019/test_case.h @@ -16,61 +16,21 @@ * limitations under the License. */ -TEST_CASE("t20019", "[test-case][sequence]") +TEST_CASE("t20019") { - auto [config, db] = load_config("t20019"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20019_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20019", "t20019_sequence"); - REQUIRE(diagram->name == "t20019_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20019_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("Base"), "name()")); - REQUIRE_THAT(src, HasCall(_A("Base"), _A("D1"), "impl()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("Base"), "name()")); - REQUIRE_THAT(src, HasCall(_A("Base"), _A("D2"), "impl()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "Base", "name()"), - FindMessage(j, "Base", "D1", "impl()"), - FindMessage(j, "tmain()", "Base", "name()"), - FindMessage(j, "Base", "D2", "impl()")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("Base"), "name()")); - REQUIRE_THAT(src, HasCall(_A("Base"), _A("D1"), "impl()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("Base"), "name()")); - REQUIRE_THAT(src, HasCall(_A("Base"), _A("D2"), "impl()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "Base", "name()"}, // + {"Base", "D1", "impl()"}, // + {"tmain()", "Base", "name()"}, // + {"Base", "D2", "impl()"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20020/test_case.h b/tests/t20020/test_case.h index bc5c2d0d..55c8cd13 100644 --- a/tests/t20020/test_case.h +++ b/tests/t20020/test_case.h @@ -16,95 +16,30 @@ * limitations under the License. */ -TEST_CASE("t20020", "[test-case][sequence]") +TEST_CASE("t20020") { - auto [config, db] = load_config("t20020"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20020_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20020", "t20020_sequence"); - REQUIRE(diagram->name == "t20020_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20020_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a1()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a2()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a3()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b1()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b2()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "log()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("C"), "c1() const")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("C"), _A("C"), "c2() const")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "log() const")); - - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("C"), "c3(int)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = {FindMessage(j, "tmain()", "A", "a1()"), - FindMessage(j, "tmain()", "A", "a5()"), - FindMessage(j, "tmain()", "A", "a2()"), - FindMessage(j, "tmain()", "C", "c3(int)"), - FindMessage(j, "tmain()", "B", "b1()"), - FindMessage(j, "tmain()", "A", "a3()"), - FindMessage(j, "tmain()", "B", "b2()"), - FindMessage(j, "tmain()", "A", "a4()"), - FindMessage(j, "tmain()", "B", "log()"), - FindMessage(j, "tmain()", "C", "c1() const"), - FindMessage(j, "C", "C", "c2() const"), - FindMessage(j, "C", "C", "log() const"), - FindMessage(j, "tmain()", "D", "d1(int,int)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - using mermaid::HasCallInControlCondition; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a1()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a2()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a3()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b1()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b2()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "log()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("C"), "c1() const")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("C"), _A("C"), "c2() const")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "log() const")); - - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("C"), "c3(int)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "a1()"}, // + {"tmain()", "A", "a5()"}, // + {"tmain()", "A", "a2()", InControlCondition{}}, // + {"tmain()", "C", "c3(int)", InControlCondition{}}, // + {"tmain()", "B", "b1()"}, // + {"tmain()", "A", "a3()", InControlCondition{}}, // + {"tmain()", "B", "b2()"}, // + {"tmain()", "A", "a4()"}, // + {"tmain()", "B", "log()"}, // + {"tmain()", "C", "c1() const"}, // + {"C", "C", "c2() const", InControlCondition{}}, // + {"C", "C", "log() const"}, // + {"tmain()", "D", "d1(int,int)"}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20021/test_case.h b/tests/t20021/test_case.h index afcedf98..6179831d 100644 --- a/tests/t20021/test_case.h +++ b/tests/t20021/test_case.h @@ -16,102 +16,28 @@ * limitations under the License. */ -TEST_CASE("t20021", "[test-case][sequence]") +TEST_CASE("t20021") { - auto [config, db] = load_config("t20021"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20021_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20021", "t20021_sequence"); - REQUIRE(diagram->name == "t20021_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20021_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a1()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a2()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a3()")); - - REQUIRE_THAT(src, !HasCall(_A("tmain()"), _A("B"), "b1()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b2()")); - - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("C"), "c1()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("C"), "c2()")); - - // TODO: Why is this not working? - // REQUIRE_THAT( - // puml, HasCallInControlCondition(_A("tmain()"), _A("C"), - // "c3()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("C"), "c4()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "c5()")); - REQUIRE_THAT(src, - HasCallInControlCondition(_A("tmain()"), _A("C"), "contents()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "C", "c4()"), - FindMessage(j, "C", "C", "c5()"), - FindMessage(j, "tmain()", "A", "a3()"), - FindMessage(j, "tmain()", "A", "a2()"), - FindMessage(j, "tmain()", "C", "c1()"), - FindMessage(j, "tmain()", "C", "c2()"), - FindMessage(j, "tmain()", "A", "a1()"), - FindMessage(j, "tmain()", "C", "c3()"), - FindMessage(j, "tmain()", "B", "b2() const"), - FindMessage(j, "tmain()", "C", "contents()") - // TODO: Repeated messge gets wrong index - // FindMessage(j, "tmain()", "B", "b2()") - }; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - using mermaid::HasCallInControlCondition; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a1()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a2()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a3()")); - - REQUIRE_THAT(src, !HasCall(_A("tmain()"), _A("B"), "b1()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b2()")); - - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("C"), "c1()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("C"), "c2()")); - - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("C"), "c4()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "c5()")); - REQUIRE_THAT(src, - HasCallInControlCondition(_A("tmain()"), _A("C"), "contents()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "C", "c4()", InControlCondition{}}, // + {"C", "C", "c5()"}, // + {"tmain()", "A", "a3()"}, // + {"tmain()", "A", "a2()", InControlCondition{}}, // + {"tmain()", "C", "c1()", InControlCondition{}}, // + {"tmain()", "C", "c2()", InControlCondition{}}, // + {"tmain()", "A", "a1()"}, // + {"tmain()", "C", "c3()", InControlCondition{}}, // + {"tmain()", "B", "b2() const"}, // + {"tmain()", "C", "contents()", InControlCondition{}}, // + {"tmain()", "B", "b2() const"}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20022/test_case.h b/tests/t20022/test_case.h index 330e14fa..0f6d284e 100644 --- a/tests/t20022/test_case.h +++ b/tests/t20022/test_case.h @@ -16,53 +16,23 @@ * limitations under the License. */ -TEST_CASE("t20022", "[test-case][sequence]") +TEST_CASE("t20022") { - auto [config, db] = load_config("t20022"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20022_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20022", "t20022_sequence"); - REQUIRE(diagram->name == "t20022_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20022_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("B"), "b()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = {FindMessage(j, "tmain()", "A", "a()"), - FindMessage(j, "A", "B", "b()")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("B"), "b()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + // TODO: ")" is incorrently rendered by PlantUML + // in a way that ) is bold, if it was ) it's rendered + // properly + {"tmain()", "A", "A(std::unique_ptr)"}, // + {"tmain()", "A", "a()"}, // + {"A", "B", "b()"}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20023/test_case.h b/tests/t20023/test_case.h index 130d06b8..dec644c4 100644 --- a/tests/t20023/test_case.h +++ b/tests/t20023/test_case.h @@ -16,60 +16,22 @@ * limitations under the License. */ -TEST_CASE("t20023", "[test-case][sequence]") +TEST_CASE("t20023") { - auto [config, db] = load_config("t20023"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20023_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20023", "t20023_sequence"); - REQUIRE(diagram->name == "t20023_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20023_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a1()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a2()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a3()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a4()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = {FindMessage(j, "tmain()", "A", "a()"), - FindMessage(j, "A", "A", "a1()"), FindMessage(j, "A", "A", "a2()"), - FindMessage(j, "A", "A", "a3()"), FindMessage(j, "A", "A", "a4()")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a1()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a2()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a3()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a4()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "a()"}, // + {"A", "A", "a2()"}, // + {"A", "A", "a2()"}, // + {"A", "A", "a3()"}, // + {"A", "A", "a4()"}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20024/test_case.h b/tests/t20024/test_case.h index 46d85a0b..e61ecaaf 100644 --- a/tests/t20024/test_case.h +++ b/tests/t20024/test_case.h @@ -16,71 +16,28 @@ * limitations under the License. */ -TEST_CASE("t20024", "[test-case][sequence]") +TEST_CASE("t20024") { - auto [config, db] = load_config("t20024"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20024_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20024", "t20024_sequence"); - REQUIRE(diagram->name == "t20024_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "select(enum_a)"}, // + {"A", "A", "a0()"}, // + {"A", "A", "a1()"}, // + {"A", "A", "a2()"}, // + {"A", "A", "a3()"}, // - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20024_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "select(enum_a)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a0()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a1()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a2()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a3()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "select(colors)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "red()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "orange()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "green()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "A", "select(enum_a)"), - FindMessage(j, "A", "A", "a0()"), FindMessage(j, "A", "A", "a1()"), - FindMessage(j, "A", "A", "a2()"), FindMessage(j, "A", "A", "a3()")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "select(enum_a)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a0()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a1()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a2()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "a3()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "select(colors)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "red()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "orange()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "green()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "B", "select(colors)"}, // + {"B", "B", "red()"}, // + {"B", "B", "orange()"}, // + {"B", "B", "green()"}, // + {"B", "B", "grey()"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20025/test_case.h b/tests/t20025/test_case.h index 2875c4f7..c3c9fa13 100644 --- a/tests/t20025/test_case.h +++ b/tests/t20025/test_case.h @@ -16,60 +16,19 @@ * limitations under the License. */ -TEST_CASE("t20025", "[test-case][sequence]") +TEST_CASE("t20025") { - auto [config, db] = load_config("t20025"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20025_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20025", "t20025_sequence"); - REQUIRE(diagram->name == "t20025_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20025_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "a1()")); - // REQUIRE_THAT(puml, !HasCall(_A("A"), _A("A"), "a2()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("add(int,int)"), "")); - REQUIRE_THAT(src, !HasCall(_A("tmain()"), _A("add2(int,int)"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = {FindMessage(j, "tmain()", "A", "a()"), - // FindMessage(j, "tmain()", "A", "a2()"), - FindMessage(j, "tmain()", "add(int,int)", "")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "a1()")); - // REQUIRE_THAT(puml, !HasCall(_A("A"), _A("A"), "a2()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("add(int,int)"), "")); - REQUIRE_THAT(src, !HasCall(_A("tmain()"), _A("add2(int,int)"), "")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "a()"}, // + {"tmain()", "add(int,int)", ""} // + })); + }); } \ No newline at end of file diff --git a/tests/t20026/test_case.h b/tests/t20026/test_case.h index be0bf34d..1533d993 100644 --- a/tests/t20026/test_case.h +++ b/tests/t20026/test_case.h @@ -16,50 +16,18 @@ * limitations under the License. */ -TEST_CASE("t20026", "[test-case][sequence]") +TEST_CASE("t20026") { - auto [config, db] = load_config("t20026"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20026_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20026", "t20026_sequence"); - REQUIRE(diagram->name == "t20026_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20026_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = {FindMessage(j, "tmain()", "A", "a()")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "a()"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20027/test_case.h b/tests/t20027/test_case.h index 97f42249..faa3bb66 100644 --- a/tests/t20027/test_case.h +++ b/tests/t20027/test_case.h @@ -16,54 +16,21 @@ * limitations under the License. */ -TEST_CASE("t20027", "[test-case][sequence]") +TEST_CASE("t20027") { - auto [config, db] = load_config("t20027"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20027_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20027", "t20027_sequence"); - REQUIRE(diagram->name == "t20027_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "a()"} // + })); - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20027_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "aa()")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "aaa()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = {FindMessage(j, "tmain()", "A", "a()")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "aa()")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "aaa()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!HasMessage(src, {"A", "A", "aa()"})); + REQUIRE(!HasMessage(src, {"A", "A", "aaa()"})); + }); } \ No newline at end of file diff --git a/tests/t20028/test_case.h b/tests/t20028/test_case.h index e0947a9f..b6128e6f 100644 --- a/tests/t20028/test_case.h +++ b/tests/t20028/test_case.h @@ -16,64 +16,23 @@ * limitations under the License. */ -TEST_CASE("t20028", "[test-case][sequence]") +TEST_CASE("t20028") { - auto [config, db] = load_config("t20028"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20028_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20028", "t20028_sequence"); - REQUIRE(diagram->name == "t20028_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "a()", InControlCondition{}}, // + {"tmain()", "A", "b()"}, // + {"tmain()", "A", "c()"}, // + {"tmain()", "A", "d()"}, // + })); - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20028_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "b()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "c()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "d()")); - REQUIRE_THAT(src, !HasCall(_A("tmain()"), _A("B"), "e()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = {FindMessage(j, "tmain()", "A", "a()"), - FindMessage(j, "tmain()", "A", "b()"), - FindMessage(j, "tmain()", "A", "c()"), - FindMessage(j, "tmain()", "A", "d()")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - using mermaid::HasCallInControlCondition; - - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "b()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "c()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "d()")); - REQUIRE_THAT(src, !HasCall(_A("tmain()"), _A("B"), "e()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!HasMessage(src, {"tmain()", "B", "e()"})); + }); } \ No newline at end of file diff --git a/tests/t20029/test_case.h b/tests/t20029/test_case.h index cfbfc6c4..c28a6860 100644 --- a/tests/t20029/test_case.h +++ b/tests/t20029/test_case.h @@ -16,143 +16,49 @@ * limitations under the License. */ -TEST_CASE("t20029", "[test-case][sequence]") +TEST_CASE("t20029") { - auto [config, db] = load_config("t20029"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20029_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20029", "t20029_sequence"); - REQUIRE(diagram->name == "t20029_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "ConnectionPool", "connect()"}, // + {"tmain()", "Encoder>", + "send(std::string &&)", InControlCondition{}}, // + {"Encoder>", + "Encoder>", + "encode(std::string &&)"}, // + {"Encoder>", + "encode_b64(std::string &&)", ""}, // + {"Encoder>", "Retrier", + "send(std::string &&)"}, // + {"Retrier", "ConnectionPool", + "send(const std::string &)", InControlCondition{}} // + })); - auto model = generate_sequence_diagram(*db, diagram); + REQUIRE(!HasMessage( + src, {"ConnectionPool", "ConnectionPool", "connect_impl()"})); - REQUIRE(model->name() == "t20029_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(HasMessageComment(src, "tmain()", + "Establish connection to the\\n" + "remote server synchronously")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(HasMessageComment(src, "tmain()", + "Repeat for each line in the\\n" + "input stream")); - // Check if all calls exist - REQUIRE_THAT( - src, HasCall(_A("tmain()"), _A("ConnectionPool"), "connect()")); - REQUIRE_THAT(src, - HasCallInControlCondition(_A("tmain()"), - _A("Encoder>"), - "send(std::string &&)")); + REQUIRE(HasMessageComment(src, "Encoder>", + "Encode the message using\\n" + "Base64 encoding and pass\\n" + "it to the next layer")); - REQUIRE_THAT(src, - HasCall(_A("Encoder>"), - _A("Encoder>"), - "encode(std::string &&)")); - - REQUIRE_THAT(src, - HasCall(_A("Encoder>"), - _A("encode_b64(std::string &&)"), "")); - - REQUIRE_THAT(src, - HasCallInControlCondition(_A("Retrier"), - _A("ConnectionPool"), "send(const std::string &)")); - - REQUIRE_THAT(src, - !HasCall( - _A("ConnectionPool"), _A("ConnectionPool"), "connect_impl()")); - - REQUIRE_THAT(src, - HasMessageComment(_A("tmain()"), - "Establish connection to the\\n" - "remote server synchronously")); - - REQUIRE_THAT(src, - HasMessageComment(_A("tmain()"), - "Repeat for each line in the\\n" - "input stream")); - - REQUIRE_THAT(src, - HasMessageComment(_A("Encoder>"), - "Encode the message using\\n" - "Base64 encoding and pass\\n" - "it to the next layer")); - - REQUIRE_THAT(src, - HasMessageComment(_A("Retrier"), - "Repeat until send\\(\\) succeeds\\n" - "or retry count is exceeded")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - REQUIRE(!j["participants"].is_null()); - - std::vector messages = { - FindMessage(j, "tmain()", "ConnectionPool", "connect()"), - FindMessage(j, "tmain()", "Encoder>", - "send(std::string &&)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - using mermaid::HasCallInControlCondition; - using mermaid::HasMessageComment; - - REQUIRE_THAT( - src, HasCall(_A("tmain()"), _A("ConnectionPool"), "connect()")); - REQUIRE_THAT(src, - HasCallInControlCondition(_A("tmain()"), - _A("Encoder>"), - "send(std::string &&)")); - - REQUIRE_THAT(src, - HasCall(_A("Encoder>"), - _A("Encoder>"), - "encode(std::string &&)")); - - REQUIRE_THAT(src, - HasCall(_A("Encoder>"), - _A("encode_b64(std::string &&)"), "")); - - REQUIRE_THAT(src, - HasCallInControlCondition(_A("Retrier"), - _A("ConnectionPool"), "send(const std::string &)")); - - REQUIRE_THAT(src, - !HasCall( - _A("ConnectionPool"), _A("ConnectionPool"), "connect_impl()")); - - REQUIRE_THAT(src, - HasMessageComment(_A("tmain()"), - "Establish connection to the
" - "remote server synchronously")); - - REQUIRE_THAT(src, - HasMessageComment(_A("tmain()"), - "Repeat for each line in the
" - "input stream")); - - REQUIRE_THAT(src, - HasMessageComment(_A("Encoder>"), - "Encode the message using
" - "Base64 encoding and pass
" - "it to the next layer")); - - REQUIRE_THAT(src, - HasMessageComment(_A("Retrier"), - "Repeat until send\\(\\) succeeds
" - "or retry count is exceeded")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(HasMessageComment(src, "Retrier", + "Repeat until send() succeeds\\n" + "or retry count is exceeded")); + }); } \ No newline at end of file diff --git a/tests/t20030/test_case.h b/tests/t20030/test_case.h index fdda6293..88327c5d 100644 --- a/tests/t20030/test_case.h +++ b/tests/t20030/test_case.h @@ -16,75 +16,37 @@ * limitations under the License. */ -TEST_CASE("t20030", "[test-case][sequence]") +TEST_CASE("t20030") { - auto [config, db] = load_config("t20030"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20030_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20030", "t20030_sequence"); - REQUIRE(diagram->name == "t20030_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + // "clanguml::t20030::tmain(int)" + // + {"tmain(int)", "magic()", ""}, // + {"tmain(int)", "A", "A(int)"}, // + {"tmain(int)", "A", "operator+=(int)"}, // + {"A", "A", "add(int)"}, // - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20030_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain(int)"), _A("magic()"), "")); - - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "create()")); - REQUIRE_THAT( - src, HasCall(_A("tmain(int)"), _A("A"), "operator+=(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "add(int)")); - - REQUIRE_THAT(src, HasCall(_A("tmain(bool,int)"), _A("A"), "A()")); - REQUIRE_THAT( - src, HasCall(_A("tmain(bool,int)"), _A("A"), "operator+=(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "add(int)")); - REQUIRE_THAT(src, - HasCall(_A("tmain(bool,int)"), _A("A"), "operator=(const A &)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "set(int)")); - REQUIRE_THAT(src, HasCall(_A("tmain(bool,int)"), _A("A"), "value()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain(int)"), _A("magic()"), "")); - - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "create()")); - REQUIRE_THAT( - src, HasCall(_A("tmain(int)"), _A("A"), "operator+=(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "add(int)")); - - REQUIRE_THAT(src, HasCall(_A("tmain(bool,int)"), _A("A"), "A()")); - REQUIRE_THAT( - src, HasCall(_A("tmain(bool,int)"), _A("A"), "operator+=(int)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "add(int)")); - REQUIRE_THAT(src, - HasCall(_A("tmain(bool,int)"), _A("A"), "operator=(const A &)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "set(int)")); - REQUIRE_THAT(src, HasCall(_A("tmain(bool,int)"), _A("A"), "value()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + // + // "clanguml::t20030::tmain(bool,int)" + // + {"tmain(bool,int)", "A", "A()"}, // + {"A", "A", "create()"}, // + {"tmain(bool,int)", "A", "A()"}, // + {"A", "A", "create()"}, // + {"tmain(bool,int)", "A", "operator+=(int)"}, // + // + {"A", "A", "add(int)"}, // + {"tmain(bool,int)", "A", "operator=(const A &)"}, // + {"A", "A", "set(int)"}, // + {"tmain(bool,int)", "A", "value() const"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20031/test_case.h b/tests/t20031/test_case.h index f325cb53..12232577 100644 --- a/tests/t20031/test_case.h +++ b/tests/t20031/test_case.h @@ -16,82 +16,31 @@ * limitations under the License. */ -TEST_CASE("t20031", "[test-case][sequence]") +TEST_CASE("t20031") { - auto [config, db] = load_config("t20031"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20031_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20031", "t20031_sequence"); - REQUIRE(diagram->name == "t20031_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20031_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, HasCall(_A("tmain(int)"), _A("magic()"), "")); - - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "create()")); - REQUIRE_THAT( - src, !HasCall(_A("tmain(int)"), _A("A"), "operator+=(int)")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "add(int)")); - - REQUIRE_THAT(src, !HasCall(_A("tmain(bool,int)"), _A("A"), "A()")); - REQUIRE_THAT( - src, !HasCall(_A("tmain(bool,int)"), _A("A"), "operator+=(int)")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "add(int)")); - REQUIRE_THAT(src, - !HasCall(_A("tmain(bool,int)"), _A("A"), "operator=(const A &)")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "set(int)")); - REQUIRE_THAT(src, HasCall(_A("tmain(bool,int)"), _A("A"), "value()")); - REQUIRE_THAT(src, - !HasCall(_A("tmain(bool,int)::(lambda " - "../../tests/t20031/t20031.cc:47:26)"), - _A("zero()"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain(int)"), _A("magic()"), "")); - - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "create()")); - REQUIRE_THAT( - src, !HasCall(_A("tmain(int)"), _A("A"), "operator+=(int)")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "add(int)")); - - REQUIRE_THAT(src, !HasCall(_A("tmain(bool,int)"), _A("A"), "A()")); - REQUIRE_THAT( - src, !HasCall(_A("tmain(bool,int)"), _A("A"), "operator+=(int)")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "add(int)")); - REQUIRE_THAT(src, - !HasCall(_A("tmain(bool,int)"), _A("A"), "operator=(const A &)")); - REQUIRE_THAT(src, !HasCall(_A("A"), _A("A"), "set(int)")); - REQUIRE_THAT(src, HasCall(_A("tmain(bool,int)"), _A("A"), "value()")); - REQUIRE_THAT(src, - !HasCall(_A("tmain(bool,int)::(lambda " - "../../tests/t20031/t20031.cc:47:26)"), - _A("zero()"), "")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain(int)", "magic()", ""}, // + {"tmain(bool,int)", "execute(std::function)", ""}, // + {"tmain(bool,int)", "A", "value() const"} // + })); + REQUIRE(!HasMessage(src, {"A", "A", "create()"})); + REQUIRE(!HasMessage(src, {"tmain(int)", "A", "operator+=(int)"})); + REQUIRE(!HasMessage(src, {"tmain(bool,int)", "A", "A()"})); + REQUIRE(!HasMessage(src, {"tmain(bool,int)", "A", "operator+=(int)"})); + REQUIRE(!HasMessage(src, {"A", "A", "add(int)"})); + REQUIRE( + !HasMessage(src, {"tmain(bool,int)", "A", "operator=(const A &)"})); + REQUIRE(!HasMessage(src, {"A", "A", "set(int)"})); + REQUIRE(!HasMessage(src, + {"tmain(bool,int)::(lambda ../../tests/t20031/t20031.cc:47:26)", + "zero()", ""})); + }); } \ No newline at end of file diff --git a/tests/t20032/test_case.h b/tests/t20032/test_case.h index c056ed62..88ec1dd3 100644 --- a/tests/t20032/test_case.h +++ b/tests/t20032/test_case.h @@ -16,89 +16,31 @@ * limitations under the License. */ -TEST_CASE("t20032", "[test-case][sequence]") +TEST_CASE("t20032") { - auto [config, db] = load_config("t20032"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20032_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20032", "t20032_sequence"); - REQUIRE(diagram->name == "t20032_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain(int,char **)", "B", "b(int)"}, // + {"B", "A", "a1(int)"}, // + {"A", "B", "int", Response{}}, // + {"B", "tmain(int,char **)", "int", Response{}}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain(int,char **)", "B", "b(double)"}, // + {"B", "A", "a2(double)"}, // + {"A", "B", "double", Response{}}, // + {"B", "tmain(int,char **)", "double", Response{}}, // - REQUIRE(model->name() == "t20032_sequence"); - - REQUIRE(model->name() == "t20032_sequence"); - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(int)")); - REQUIRE_THAT( - src, HasResponse(_A("tmain(int,char **)"), _A("B"), "int")); - - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int)")); - REQUIRE_THAT(src, HasResponse(_A("B"), _A("A"), "int")); - - REQUIRE_THAT( - src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(double)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2(double)")); - REQUIRE_THAT(src, HasResponse(_A("B"), _A("A"), "double")); - - REQUIRE_THAT( - src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(const char *)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a3(const char *)")); - REQUIRE_THAT(src, HasResponse(_A("B"), _A("A"), "const char *")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain(int,char **)", "B", "b(int)", "int"), - FindMessage(j, "B", "A", "a1(int)", "int"), - FindMessage(j, "tmain(int,char **)", "B", "b(double)"), - FindMessage(j, "B", "A", "a2(double)"), - FindMessage(j, "tmain(int,char **)", "B", "b(const char *)"), - FindMessage(j, "B", "A", "a3(const char *)")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - using mermaid::HasResponse; - - REQUIRE_THAT(src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(int)")); - REQUIRE_THAT( - src, HasResponse(_A("tmain(int,char **)"), _A("B"), "int")); - - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a1(int)")); - REQUIRE_THAT(src, HasResponse(_A("B"), _A("A"), "int")); - - REQUIRE_THAT( - src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(double)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2(double)")); - REQUIRE_THAT(src, HasResponse(_A("B"), _A("A"), "double")); - - REQUIRE_THAT( - src, HasCall(_A("tmain(int,char **)"), _A("B"), "b(const char *)")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a3(const char *)")); - REQUIRE_THAT(src, HasResponse(_A("B"), _A("A"), "const char *")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain(int,char **)", "B", "b(const char *)"}, // + {"B", "A", "a3(const char *)"}, // + {"A", "B", "const char *", Response{}}, // + {"B", "tmain(int,char **)", "const char *", Response{}} // + })); + }); } \ No newline at end of file diff --git a/tests/t20033/test_case.h b/tests/t20033/test_case.h index f1f10c63..83a483bc 100644 --- a/tests/t20033/test_case.h +++ b/tests/t20033/test_case.h @@ -16,60 +16,40 @@ * limitations under the License. */ -TEST_CASE("t20033", "[test-case][sequence]") +TEST_CASE("t20033") { - auto [config, db] = load_config("t20033"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20033_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20033", "t20033_sequence"); - REQUIRE(diagram->name == "t20033_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "a1()"}, // + {"tmain()", "A", "a2()"}, // + {"tmain()", "A", "a2()", InControlCondition{}}, // + {"tmain()", "A", "a3()", InControlCondition{}}, // + {"tmain()", "A", "a3()"}, // + {"tmain()", "A", "a4()"}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain()", "A", "a2()", InControlCondition{}}, // + {"tmain()", "A", "a3()"}, // - REQUIRE(model->name() == "t20033_sequence"); + {"tmain()", "A", "a2()", InControlCondition{}}, // + {"tmain()", "A", "a3()"}, // - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); + {"tmain()", "A", "a3()"}, // - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + {"tmain()", "A", "a2()"}, // - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a1()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a2()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a3()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a4()")); + {"tmain()", "A", "a4()"}, // + {"tmain()", "A", "a3()", InControlCondition{}}, // - save_puml(config.output_directory(), diagram->name + ".puml", src); - } + {"tmain()", "A", "a4()", InControlCondition{}}, // - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - using mermaid::HasCallInControlCondition; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a1()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a2()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a3()")); - REQUIRE_THAT( - src, HasCallInControlCondition(_A("tmain()"), _A("A"), "a4()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "A", "a4()"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20034/test_case.h b/tests/t20034/test_case.h index 26290368..45d8ff59 100644 --- a/tests/t20034/test_case.h +++ b/tests/t20034/test_case.h @@ -16,79 +16,59 @@ * limitations under the License. */ -TEST_CASE("t20034", "[test-case][sequence]") +TEST_CASE("t20034") { - auto [config, db] = load_config("t20034"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20034_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20034", "t20034_sequence"); - REQUIRE(diagram->name == "t20034_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20034_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("D"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("D"), _A("C"), "c3()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "c2()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b2()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("D"), _A("C"), "c4()")); - - REQUIRE_THAT(src, !HasCall(_A("C"), _A("B"), "b3()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - REQUIRE(HasMessageChain(j, - {{"d2()", "c3()", "void"}, {"c3()", "c2()", "void"}, - {"c2()", "b2()", "void"}, {"b2()", "a2()", "void"}})); - REQUIRE(HasMessageChain(j, - {{"d2()", "c4()", "void"}, {"c4()", "b4()", "void"}, - {"b4()", "b2()", "void"}, {"b2()", "a2()", "void"}})); - REQUIRE(HasMessageChain(j, {{"d2()", "a2()", "void"}})); - REQUIRE(HasMessageChain(j, - {{"d2()", "c1()", "void"}, {"c1()", "b1()", "void"}, - {"b1()", "a2()", "void"}})); - REQUIRE(HasMessageChain(j, - {{"d2()", "c2()", "void"}, {"c2()", "b2()", "void"}, - {"b2()", "a2()", "void"}})); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("D"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("D"), _A("C"), "c3()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "c2()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b2()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("D"), _A("C"), "c4()")); - - REQUIRE_THAT(src, !HasCall(_A("C"), _A("B"), "b3()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageChainsOrder(src, + { + // + { + // + {Entrypoint{}, "D", "d2()"}, // + {"D", "C", "c2()"}, // + {"C", "B", "b2()"}, // + {"B", "A", "a2()"} // + }, // + { + // + {Entrypoint{}, "D", "d2()"}, // + {"D", "D::d2()::(lambda t20034.cc:56:18)", + "operator()() const"}, // + {"D::d2()::(lambda t20034.cc:56:18)", "A", "a2()"} // + }, // + { + // + {Entrypoint{}, "D", "d2()"}, // + {"D", "A", "a2()"} // + }, // + { + // + {Entrypoint{}, "D", "d2()"}, // + {"D", "C", "c4()"}, // + {"C", "B", "b4()"}, // + {"B", "B", "b2()"}, // + {"B", "A", "a2()"} // + }, // + { + // + {Entrypoint{}, "D", "d2()"}, // + {"D", "C", "c1()"}, // + {"C", "B", "b1()"}, // + {"B", "A", "a2()"} // + }, // + { + // + {Entrypoint{}, "D", "d2()"}, // + {"D", "C", "c3()"}, // + {"C", "C", "c2()"}, // + {"C", "B", "b2()"}, // + {"B", "A", "a2()"} // + } // + })); + }); } \ No newline at end of file diff --git a/tests/t20035/test_case.h b/tests/t20035/test_case.h index 8213597d..0549da2a 100644 --- a/tests/t20035/test_case.h +++ b/tests/t20035/test_case.h @@ -16,54 +16,20 @@ * limitations under the License. */ -TEST_CASE("t20035", "[test-case][sequence]") +TEST_CASE("t20035") { - auto [config, db] = load_config("t20035"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20035_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20035", "t20035_sequence"); - REQUIRE(diagram->name == "t20035_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20035_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, HasCall(_A("tmain(int,char **)"), _A("a(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("a(int)"), _A("b1(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("b1(int)"), _A("c(int)"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - REQUIRE(HasMessageChain(j, - {{"tmain(int,char **)", "a(int)", "int"}, - {"a(int)", "b1(int)", "int"}, {"b1(int)", "c(int)", "int"}})); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain(int,char **)"), _A("a(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("a(int)"), _A("b1(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("b1(int)"), _A("c(int)"), "")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageChainsOrder(src, + {{ + // + {"tmain(int,char **)", "a(int)", ""}, // + {"a(int)", "b1(int)", ""}, // + {"b1(int)", "c(int)", ""} // + }})); + }); } \ No newline at end of file diff --git a/tests/t20036/test_case.h b/tests/t20036/test_case.h index f8da4cd2..a96a06f9 100644 --- a/tests/t20036/test_case.h +++ b/tests/t20036/test_case.h @@ -16,78 +16,55 @@ * limitations under the License. */ -TEST_CASE("t20036", "[test-case][sequence]") +TEST_CASE("t20036") { - auto [config, db] = load_config("t20036"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20036_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20036", "t20036_sequence"); - REQUIRE(diagram->name == "t20036_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20036_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "c2()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b2()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b2()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("D"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b1()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - REQUIRE(HasMessageChain(j, - {{"c3()", "c2()", "void"}, {"c2()", "b2()", "void"}, - {"b2()", "a2()", "void"}})); - REQUIRE(HasMessageChain( - j, {{"c4()", "b2()", "void"}, {"b2()", "a2()", "void"}})); - REQUIRE(HasMessageChain(j, {{"d3()", "a2()", "void"}})); - REQUIRE(HasMessageChain(j, - {{"d1()", "c2()", "void"}, {"c2()", "b2()", "void"}, - {"b2()", "a2()", "void"}})); - REQUIRE(HasMessageChain( - j, {{"c1()", "b1()", "void"}, {"b1()", "a2()", "void"}})); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "c2()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b2()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b2()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("D"), _A("A"), "a2()")); - - REQUIRE_THAT(src, HasCall(_A("C"), _A("B"), "b1()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("A"), "a2()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageChainsOrder(src, + { + // + { + // + {Entrypoint{}, "C", "c1()"}, // + {"C", "B", "b1()"}, // + {"B", "A", "a2()"}, // + }, // + { + // + {Entrypoint{}, "D", "d1()"}, // + {"D", "C", "c2()"}, // + {"C", "B", "b2()"}, // + {"B", "A", "a2()"}, // + }, // + { + // + {Entrypoint{}, "D", "d3()"}, // + {"D", "A", "a2()"}, // + }, // + { + // + {Entrypoint{}, "C", "c4()"}, // + {"C", "B", "b2()"}, // + {"B", "A", "a2()"}, // + }, // + { + // + {Entrypoint{}, "C", "c3()"}, // + {"C", "C", "c2()"}, // + {"C", "B", "b2()"}, // + {"B", "A", "a2()"}, // + }, // + { + // + {Entrypoint{}, "D", "d2()"}, // + {"D", "C", "c2()"}, // + {"C", "B", "b2()"}, // + {"B", "A", "a2()"}, // + }, // + })); + }); } \ No newline at end of file diff --git a/tests/t20037/test_case.h b/tests/t20037/test_case.h index 15f20df3..4a18a5d3 100644 --- a/tests/t20037/test_case.h +++ b/tests/t20037/test_case.h @@ -16,60 +16,30 @@ * limitations under the License. */ -TEST_CASE("t20037", "[test-case][sequence]") +TEST_CASE("t20037") { - auto [config, db] = load_config("t20037"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20037_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20037", "t20037_sequence"); - REQUIRE(diagram->name == "t20037_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain(int,char **)", "a()", ""}, // + {"a()", "A", "A()"}, // + {"a()", "initb()", ""}, // + {"a()", "B", "get()"}, // + {"a()", "c()", ""}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain(int,char **)", "a()", ""}, // + {"a()", "B", "get()"}, // + {"a()", "c()", ""}, // - REQUIRE(model->name() == "t20037_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, HasCall(_A("tmain(int,char **)"), _A("a()"), "")); - REQUIRE_THAT(src, HasCall(_A("a()"), _A("initb()"), "")); - REQUIRE_THAT(src, HasCall(_A("a()"), _A("B"), "get()")); - REQUIRE_THAT(src, HasCall(_A("a()"), _A("c()"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain(int,char **)", "a()", ""), - FindMessage(j, "a()", "initb()", ""), - FindMessage(j, "a()", "B", "get()"), - FindMessage(j, "a()", "c()", "")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain(int,char **)"), _A("a()"), "")); - REQUIRE_THAT(src, HasCall(_A("a()"), _A("initb()"), "")); - REQUIRE_THAT(src, HasCall(_A("a()"), _A("B"), "get()")); - REQUIRE_THAT(src, HasCall(_A("a()"), _A("c()"), "")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain(int,char **)", "a()", ""}, // + {"a()", "B", "get()"}, // + {"a()", "c()", ""} // + })); + }); } \ No newline at end of file diff --git a/tests/t20038/test_case.h b/tests/t20038/test_case.h index dc0c8be9..33e01e7e 100644 --- a/tests/t20038/test_case.h +++ b/tests/t20038/test_case.h @@ -16,110 +16,41 @@ * limitations under the License. */ -TEST_CASE("t20038", "[test-case][sequence]") +TEST_CASE("t20038") { - auto [config, db] = load_config("t20038"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20038_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20038", "t20038_sequence"); - REQUIRE(diagram->name == "t20038_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "B", "b()"}, // + {"B", "A", "a()"}, // + {"tmain()", "B", "b()"}, // + {"B", "A", "a()"}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain()", "B", "bbb()"}, // + {"B", "A", "aaa()"}, // - REQUIRE(model->name() == "t20038_sequence"); + {"tmain()", "B", "bbbb()"}, // + {"B", "A", "aaaa()"}, // + {"A", "add(int,int)", ""}, // + {"add(int,int)", "add_impl(int,int)", ""}, // - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); + {"tmain()", "B", "wrap(int)"}, // - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + {"tmain()", "add_impl(double,double)", ""}, // - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b()")); + {"tmain()", "B", "bbbbb()"}, // + {"B", "A", "aaaa()"}, // + {"A", "add(int,int)", ""}, // + {"add(int,int)", "add_impl(int,int)", ""}, // - REQUIRE_THAT(src, !HasCall(_A("tmain()"), _A("B"), "bb()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "bbb()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "bbbb()")); - - REQUIRE_THAT(src, - HasMessageComment(_A("tmain()"), - "This comment should be rendered only\\n" - "once")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("add_impl(double,double)"), "")); - - REQUIRE_THAT( - src, HasMessageComment(_A("tmain()"), "What is 2 \\+ 2\\?")); - - REQUIRE_THAT(src, - !HasMessageComment( - _A("tmain()"), "This is specific for some_other_diagram")); - - REQUIRE_THAT( - src, HasMessageComment(_A("tmain()"), "Calling B::bbbbb\\(\\)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "bbbbb()")); - - REQUIRE_THAT(src, - HasMessageComment(_A("tmain()"), "This is a conditional operator")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - using mermaid::HasCallInControlCondition; - using mermaid::HasMessageComment; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b()")); - - REQUIRE_THAT(src, !HasCall(_A("tmain()"), _A("B"), "bb()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "bbb()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "bbbb()")); - - REQUIRE_THAT(src, - HasMessageComment(_A("tmain()"), - "This comment should be rendered only
" - "once")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("add_impl(double,double)"), "")); - - REQUIRE_THAT( - src, HasMessageComment(_A("tmain()"), "What is 2 \\+ 2\\?")); - - REQUIRE_THAT(src, - !HasMessageComment( - _A("tmain()"), "This is specific for some_other_diagram")); - - REQUIRE_THAT( - src, HasMessageComment(_A("tmain()"), "Calling B::bbbbb\\(\\)")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "bbbbb()")); - - REQUIRE_THAT(src, - !HasMessageComment( - _A("tmain()"), "This is specific for some_other_diagram")); - - REQUIRE_THAT( - src, HasMessageComment(_A("tmain()"), "Calling B::bbbbb\\(\\)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "B", "bbb()", InControlCondition{}}, // + {"B", "A", "aaa()"}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20039/test_case.h b/tests/t20039/test_case.h index 316d20e0..88a011f6 100644 --- a/tests/t20039/test_case.h +++ b/tests/t20039/test_case.h @@ -16,61 +16,23 @@ * limitations under the License. */ -TEST_CASE("t20039", "[test-case][sequence]") +TEST_CASE("t20039") { - auto [config, db] = load_config("t20039"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20039_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20039", "t20039_sequence"); - REQUIRE(diagram->name == "t20039_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20039_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("R"), "run()")); - REQUIRE_THAT(src, HasCall(_A("R"), _A("A"), "a(int)")); - REQUIRE_THAT(src, HasCall(_A("R"), _A("A"), "a(int_vec_t)")); - REQUIRE_THAT( - src, HasCall(_A("R"), _A("A"), "a(string_vec_t)")); - REQUIRE_THAT(src, HasCall(_A("R"), _A("A"), "a(int_map_t)")); - REQUIRE_THAT( - src, HasCall(_A("R"), _A("A"), "a(string_map_t)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("R"), "run()")); - REQUIRE_THAT(src, HasCall(_A("R"), _A("A"), "a(int)")); - REQUIRE_THAT(src, HasCall(_A("R"), _A("A"), "a(int_vec_t)")); - REQUIRE_THAT( - src, HasCall(_A("R"), _A("A"), "a(string_vec_t)")); - REQUIRE_THAT(src, HasCall(_A("R"), _A("A"), "a(int_map_t)")); - REQUIRE_THAT( - src, HasCall(_A("R"), _A("A"), "a(string_map_t)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "R", "run()"}, // + {"R", "A", "a(int)"}, // + {"R", "A", "a(int_vec_t)"}, // + {"R", "A", "a(string_vec_t)"}, // + {"R", "A", "a(int_map_t)"}, // + {"R", "A", "a(string_map_t)"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20040/test_case.h b/tests/t20040/test_case.h index 9ff98228..87277908 100644 --- a/tests/t20040/test_case.h +++ b/tests/t20040/test_case.h @@ -16,74 +16,33 @@ * limitations under the License. */ -TEST_CASE("t20040", "[test-case][sequence]") +TEST_CASE("t20040") { - auto [config, db] = load_config("t20040"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20040_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20040", "t20040_sequence"); - REQUIRE(diagram->name == "t20040_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", + "print(int,double,std::string)", + ""}, // + {"print(int,double,std::string)", + "print(double,std::string)", ""}, // + {"print(double,std::string)", + "print(std::string)", ""}, // + {"print(std::string)", "print()", ""}, // - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20040_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("print(int,double,std::string)"), - "")); - - REQUIRE_THAT(src, - HasCall(_A("print(int,double,std::string)"), - _A("print(double,std::string)"), "")); - - REQUIRE_THAT(src, - HasCall(_A("print(double,std::string)"), - _A("print(std::string)"), "")); - - REQUIRE_THAT(src, - HasCall(_A("print(std::string)"), _A("print()"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("print(int,double,std::string)"), - "")); - - REQUIRE_THAT(src, - HasCall(_A("print(int,double,std::string)"), - _A("print(double,std::string)"), "")); - - REQUIRE_THAT(src, - HasCall(_A("print(double,std::string)"), - _A("print(std::string)"), "")); - - REQUIRE_THAT(src, - HasCall(_A("print(std::string)"), _A("print()"), "")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "doublePrint(std::string,int)", + ""}, // + {"doublePrint(std::string,int)", + "print(std::string,int)", ""}, // + {"print(std::string,int)", "print(int)", + ""}, // + {"print(int)", "print()", ""}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20041/test_case.h b/tests/t20041/test_case.h index c3198068..044de4a7 100644 --- a/tests/t20041/test_case.h +++ b/tests/t20041/test_case.h @@ -16,74 +16,24 @@ * limitations under the License. */ -TEST_CASE("t20041", "[test-case][sequence]") +TEST_CASE("t20041") { - auto [config, db] = load_config("t20041"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20041_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20041", "t20041_sequence"); - REQUIRE(diagram->name == "t20041_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20041_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("A"), - "print(int,double,std::string)")); - REQUIRE_THAT(src, - HasCall(_A("A"), - _A("A"), "print(double,std::string)")); - REQUIRE_THAT(src, - HasCall(_A("A"), _A("A"), - "print(std::string)")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "print()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "A", - "print(int,double,std::string)"), - FindMessage(j, "A", "A", - "print(double,std::string)"), - FindMessage(j, "A", "A", - "print(std::string)"), - FindMessage(j, "A", "A", "print()")}; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("A"), - "print(int,double,std::string)")); - REQUIRE_THAT(src, - HasCall(_A("A"), - _A("A"), "print(double,std::string)")); - REQUIRE_THAT(src, - HasCall(_A("A"), _A("A"), - "print(std::string)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", + "print(int,double,std::string)"}, // + {"A", "A", + "print(double,std::string)"}, // + {"A", "A", + "print(std::string)"}, // + {"A", "A", "print()"}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20042/test_case.h b/tests/t20042/test_case.h index 3e2276d8..4a36b7b0 100644 --- a/tests/t20042/test_case.h +++ b/tests/t20042/test_case.h @@ -16,60 +16,22 @@ * limitations under the License. */ -TEST_CASE("t20042", "[test-case][sequence]") +TEST_CASE("t20042") { - auto [config, db] = load_config("t20042"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20042_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20042", "t20042_sequence"); - REQUIRE(diagram->name == "t20042_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "AHandler", "operator()(A &) const"}, // + {"AHandler", "AHandler", "handle(A &) const"}, // - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20042_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("AHandler"), "operator()(A &) const")); - REQUIRE_THAT( - src, HasCall(_A("AHandler"), _A("AHandler"), "handle(A &) const")); - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("BHandler"), "operator()(B &) const")); - REQUIRE_THAT( - src, HasCall(_A("BHandler"), _A("BHandler"), "handle(B &) const")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("AHandler"), "operator()(A &) const")); - REQUIRE_THAT( - src, HasCall(_A("AHandler"), _A("AHandler"), "handle(A &) const")); - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("BHandler"), "operator()(B &) const")); - REQUIRE_THAT( - src, HasCall(_A("BHandler"), _A("BHandler"), "handle(B &) const")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "BHandler", "operator()(B &) const"}, // + {"BHandler", "BHandler", "handle(B &) const"}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20043/test_case.h b/tests/t20043/test_case.h index 84c0a4e9..60ee3d59 100644 --- a/tests/t20043/test_case.h +++ b/tests/t20043/test_case.h @@ -16,58 +16,25 @@ * limitations under the License. */ -TEST_CASE("t20043", "[test-case][sequence]") +TEST_CASE("t20043") { - auto [config, db] = load_config("t20043"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20043_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20043", "t20043_sequence"); - REQUIRE(diagram->name == "t20043_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "D", "d()"}, // + {"D", "C", "c()"}, // + })); - auto model = generate_sequence_diagram(*db, diagram); + REQUIRE(!HasMessage(src, {"tmain()", "F", "f()"})); - REQUIRE(model->name() == "t20043_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, !HasCall(_A("tmain()"), _A("F"), "f()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("D"), "d()")); - - REQUIRE_THAT(src, HasCall(_A("D"), _A("C"), "c()")); - REQUIRE_THAT(src, !HasCall(_A("D"), _A("detail::E"), "e()")); - REQUIRE_THAT(src, !HasCall(_A("C"), _A("B"), "b()")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("A"), "a()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, !HasCall(_A("tmain()"), _A("F"), "f()")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("D"), "d()")); - - REQUIRE_THAT(src, HasCall(_A("D"), _A("C"), "c()")); - REQUIRE_THAT(src, !HasCall(_A("D"), _A("detail::E"), "e()")); - REQUIRE_THAT(src, !HasCall(_A("C"), _A("B"), "b()")); - REQUIRE_THAT(src, !HasCall(_A("B"), _A("A"), "a()")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(!HasMessage(src, {"D", {"detail", "E"}, "e()"})); + REQUIRE(!HasMessage(src, {"C", "B", "b()"})); + REQUIRE(!HasMessage(src, {"B", "A", "a()"})); + }); } \ No newline at end of file diff --git a/tests/t20044/.clang-uml b/tests/t20044/.clang-uml index 3526dcf7..bb1a0dcc 100644 --- a/tests/t20044/.clang-uml +++ b/tests/t20044/.clang-uml @@ -6,7 +6,7 @@ diagrams: glob: - t20044.cc type_aliases: - "detail::expected": result_t + "clanguml::t20044::detail::expected": result_t generate_message_comments: true include: namespaces: diff --git a/tests/t20044/test_case.h b/tests/t20044/test_case.h index 3ff700b3..66e52d93 100644 --- a/tests/t20044/test_case.h +++ b/tests/t20044/test_case.h @@ -16,77 +16,44 @@ * limitations under the License. */ -TEST_CASE("t20044", "[test-case][sequence]") +TEST_CASE("t20044") { - auto [config, db] = load_config("t20044"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20044_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20044", "t20044_sequence"); - REQUIRE(diagram->name == "t20044_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!IsClassParticipant(src, "detail::expected")); + REQUIRE(IsClassParticipant(src, "result_t")); - auto model = generate_sequence_diagram(*db, diagram); + REQUIRE(MessageOrder(src, + { + {"tmain()", "R", "R((lambda at t20044.cc:74:9) &&)"}, // + {"R", "tmain()::(lambda t20044.cc:74:9)", + "operator()() const"}, // + {"tmain()::(lambda t20044.cc:74:9)", "A", "a() const"}, // - REQUIRE(model->name() == "t20044_sequence"); + {"tmain()", "tmain()::(lambda t20044.cc:84:18)", + "operator()() const"}, // + {"tmain()::(lambda t20044.cc:84:18)", "A", "a5()"}, // - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); + {"tmain()", "A", "a1() const"}, // + {"A", "result_t", "expected(int)"}, // - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + {"tmain()", "result_t", + "and_then((lambda at t20044.cc:90:19) &&)"}, // + {"result_t", "tmain()::(lambda t20044.cc:90:19)", + "operator()(auto &&) const"}, // + {"tmain()::(lambda t20044.cc:90:19)", "A", "a2(int) const"}, // + {"A", "result_t", "expected(int)"}, // - // Check if all calls exist - REQUIRE_THAT(src, - HasCall( - _A("tmain()"), _A("R"), "R((lambda at t20044.cc:74:9) &&)")); - REQUIRE_THAT(src, - HasCall(_A("R"), _A("tmain()::(lambda t20044.cc:74:9)"), - "operator()()")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20044.cc:74:9)"), _A("A"), "a()")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("tmain()::(lambda t20044.cc:84:18)"), - "operator()()")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20044.cc:84:18)"), _A("A"), "a5()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a1()")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("detail::expected"), - "and_then((lambda at t20044.cc:90:19) &&)")); - - REQUIRE_THAT(src, - HasCall(_A("detail::expected"), - _A("tmain()::(lambda t20044.cc:90:19)"), - "operator()(auto &&) const")); - - REQUIRE_THAT(src, - HasCall( - _A("tmain()::(lambda t20044.cc:90:19)"), _A("A"), "a2(int)")); - - REQUIRE_THAT(src, - HasCall( - _A("A"), _A("detail::expected"), "expected(int)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "result_t", + "and_then(result_t (&)(int))"}, // // + {"tmain()", "result_t", + "and_then(std::function &)"}, // // + {"tmain()", "result_t", + "value() const"}, // // + })); + }); } \ No newline at end of file diff --git a/tests/t20045/test_case.h b/tests/t20045/test_case.h index 5d8d7775..8e4b43e5 100644 --- a/tests/t20045/test_case.h +++ b/tests/t20045/test_case.h @@ -16,68 +16,48 @@ * limitations under the License. */ -TEST_CASE("t20045", "[test-case][sequence]") +TEST_CASE("t20045") { - auto [config, db] = load_config("t20045"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20045_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20045", "t20045_sequence"); - REQUIRE(diagram->name == "t20045_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "a2(int)", ""}, // + {"tmain()", + "a1<(lambda at t20045.cc:35:18)>((lambda at " + "t20045.cc:35:18) &&)", + ""}, // + {"a1<(lambda at t20045.cc:35:18)>((lambda at t20045.cc:35:18) " + "&&)", + "tmain()::(lambda t20045.cc:35:18)", + "operator()(auto &&) const"}, // + {"tmain()::(lambda t20045.cc:35:18)", "a3(int)", ""}, // - auto model = generate_sequence_diagram(*db, diagram); + {"tmain()", + "a1<(lambda at t20045.cc:37:18)>((lambda at " + "t20045.cc:37:18) " + "&&)", + ""}, // + {"a1<(lambda at t20045.cc:37:18)>((lambda at t20045.cc:37:18) " + "&&)", + "tmain()::(lambda t20045.cc:37:18)", + "operator()(auto &&) const"}, // + {"tmain()::(lambda t20045.cc:37:18)", "B", "b1(int)"}, // - REQUIRE(model->name() == "t20045_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a2(int)"), "")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("a1<(lambda at t20045.cc:35:18)>((lambda at " - "t20045.cc:35:18) &&)"), - "")); - - REQUIRE_THAT(src, - HasCall(_A("a1<(lambda at t20045.cc:35:18)>((lambda at " - "t20045.cc:35:18) &&)"), - _A("tmain()::(lambda t20045.cc:35:18)"), - "operator()(auto &&) const")); - - REQUIRE_THAT(src, - HasCall( - _A("tmain()::(lambda t20045.cc:35:18)"), _A("a3(int)"), "")); - - REQUIRE_THAT(src, - HasCall( - _A("tmain()::(lambda t20045.cc:37:18)"), _A("B"), "b1(int)")); - - REQUIRE_THAT(src, - HasCall( - _A("tmain()::(lambda t20045.cc:39:18)"), _A("C"), "get_x()")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", + "a1<(lambda at t20045.cc:39:18)>((lambda at " + "t20045.cc:39:18) &&)", + ""}, // + {"a1<(lambda at t20045.cc:39:18)>((lambda at " + "t20045.cc:39:18) &&)", + "tmain()::(lambda t20045.cc:39:18)", + "operator()(auto &&) const"}, // + {"tmain()::(lambda t20045.cc:39:18)", "C", "get_x() const"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20046/test_case.h b/tests/t20046/test_case.h index c4ddbacb..7214fe4d 100644 --- a/tests/t20046/test_case.h +++ b/tests/t20046/test_case.h @@ -16,80 +16,41 @@ * limitations under the License. */ -TEST_CASE("t20046", "[test-case][sequence]") +TEST_CASE("t20046") { - auto [config, db] = load_config("t20046"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20046_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20046", "t20046_sequence"); - REQUIRE(diagram->name == "t20046_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "tmain()::(lambda t20046.cc:13:15)", + "operator()(auto &&) const"}, // + {"tmain()::(lambda t20046.cc:13:15)", + "tmain()::(lambda t20046.cc:13:15)::(lambda " + "t20046.cc:14:16)", + "operator()(auto &&) const"}, // + {"tmain()::(lambda t20046.cc:13:15)::(lambda " + "t20046.cc:14:16)", + "a2(int)", ""}, // - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20046_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("tmain()::(lambda t20046.cc:13:15)"), - "operator()(auto &&) const")); - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20046.cc:13:15)"), - _A("tmain()::(lambda t20046.cc:13:15)::(lambda " - "t20046.cc:14:16)"), - "operator()(auto &&) const")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20046.cc:13:15)::(lambda " - "t20046.cc:14:16)"), - _A("a2(int)"), "")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("a1<(lambda at t20046.cc:19:9)>((lambda at t20046.cc:19:9) " - "&&)"), - "")); - - REQUIRE_THAT(src, - HasCall( - _A("a1<(lambda at t20046.cc:19:9)>((lambda at t20046.cc:19:9) " - "&&)"), - _A("tmain()::(lambda t20046.cc:19:9)"), - "operator()(auto &&) const")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20046.cc:19:9)"), - _A("tmain()::(lambda t20046.cc:19:9)::(lambda " - "t20046.cc:19:34)"), - "operator()(auto &&) const")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()::(lambda t20046.cc:19:9)::(lambda " - "t20046.cc:19:34)"), - _A("a3(int)"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", + "a1<(lambda at t20046.cc:19:9)>((lambda at t20046.cc:19:9) " + "&&)", + ""}, + {"a1<(lambda at t20046.cc:19:9)>((lambda at t20046.cc:19:9) " + "&&)", + "tmain()::(lambda t20046.cc:19:9)", + "operator()(auto &&) const"}, // + {"tmain()::(lambda t20046.cc:19:9)", + "tmain()::(lambda t20046.cc:19:9)::(lambda " + "t20046.cc:19:34)", + "operator()(auto &&) const"}, // + {"tmain()::(lambda t20046.cc:19:9)::(lambda t20046.cc:19:34)", + "a3(int)", ""} // + })); + }); } \ No newline at end of file diff --git a/tests/t20047/test_case.h b/tests/t20047/test_case.h index 3643c2db..34b7b155 100644 --- a/tests/t20047/test_case.h +++ b/tests/t20047/test_case.h @@ -16,50 +16,23 @@ * limitations under the License. */ -TEST_CASE("t20047", "[test-case][sequence]") +TEST_CASE("t20047") { - auto [config, db] = load_config("t20047"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20047_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20047", "t20047_sequence"); - REQUIRE(diagram->name == "t20047_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20047_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a1(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a2(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a3(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a4(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a5(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a6(int)"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "a1(int)", ""}, // + {"tmain()", "a2(int)", ""}, // + {"tmain()", "a3(int)", ""}, // + {"tmain()", "a4(int)", ""}, // + {"tmain()", "a5(int)", ""}, // + {"tmain()", "a6(int)", ""}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20048/test_case.h b/tests/t20048/test_case.h index aa83b02f..a45632ba 100644 --- a/tests/t20048/test_case.h +++ b/tests/t20048/test_case.h @@ -16,76 +16,40 @@ * limitations under the License. */ -TEST_CASE("t20048", "[test-case][sequence]") +TEST_CASE("t20048") { - auto [config, db] = load_config("t20048"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20048_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20048", "t20048_sequence"); - REQUIRE(diagram->name == "t20048_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "a3(int)", ""}, // + {"tmain()", "a2(int)", ""}, // + {"tmain()", "a1(int)", ""}, // + {"tmain()", "tmain()::(lambda t20048.cc:26:11)", + "operator()(auto &&) const"}, // + {"tmain()::(lambda t20048.cc:26:11)", "a4(int)", ""}, // + {"tmain()", "a6(int)", ""}, // + {"tmain()", "a5(int)", ""}, // + {"tmain()", "a7(int)", ""}, // - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20048_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a3(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a2(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a1(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a5(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a6(int)"), "")); - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a7(int)"), "")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("tmain()::(lambda t20048.cc:26:11)"), - "operator()(auto &&) const")); - REQUIRE_THAT(src, - HasCall( - _A("tmain()::(lambda t20048.cc:26:11)"), _A("a4(int)"), "")); - - REQUIRE_THAT(src, - HasMessageComment(_A("tmain()"), - "a1\\(\\) adds `1` to the result\\n" - "of a2\\(\\)")); - REQUIRE_THAT(src, - HasMessageComment(_A("tmain()"), - "This lambda calls a4\\(\\) which\\n" - "adds `4` to it's argument")); - REQUIRE_THAT(src, - HasMessageComment( - _A("tmain()"), "a6\\(\\) adds `1` to its argument")); - REQUIRE_THAT(src, - HasMessageComment(_A("tmain()"), - "a5\\(\\) adds `1` to the result\\n" - "of a6\\(\\)")); - REQUIRE_THAT(src, - HasMessageComment( - _A("tmain()"), "a7\\(\\) is called via add std::async")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + })); + REQUIRE(HasMessageComment(src, "tmain()", + "a1() adds `1` to the result\\n" + "of a2()")); + REQUIRE(HasMessageComment(src, "tmain()", + "This lambda calls a4() which\\n" + "adds `4` to it's argument")); + REQUIRE( + HasMessageComment(src, "tmain()", "a6() adds `1` to its argument")); + REQUIRE(HasMessageComment(src, "tmain()", + "a5() adds `1` to the result\\n" + "of a6()")); + REQUIRE(HasMessageComment( + src, "tmain()", "a7() is called via add std::async")); + }); } \ No newline at end of file diff --git a/tests/t20049/test_case.h b/tests/t20049/test_case.h index f73722b9..6655ff89 100644 --- a/tests/t20049/test_case.h +++ b/tests/t20049/test_case.h @@ -16,66 +16,25 @@ * limitations under the License. */ -TEST_CASE("t20049", "[test-case][sequence]") +TEST_CASE("t20049") { - auto [config, db] = load_config("t20049"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20049_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20049", "t20049_sequence"); - REQUIRE(diagram->name == "t20049_sequence"); - - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20049_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("vector_square_add(float *,float *,float *,int)"), "")); - REQUIRE_THAT(src, - HasCall(_A("vector_square_add(float *,float *,float *,int)"), - _A("square(float)"), "")); - REQUIRE_THAT(src, - HasCall(_A("vector_square_add(float *,float *,float *,int)"), - _A("add(float,float)"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("<< CUDA Kernel >>
vector_square_add(float *,float " - "*,float *,int)"), - "")); - REQUIRE_THAT(src, - HasCall(_A("<< CUDA Kernel >>
vector_square_add(float *,float " - "*,float *,int)"), - _A("<< CUDA Device >>
square(float)"), "")); - REQUIRE_THAT(src, - HasCall(_A("<< CUDA Kernel >>
vector_square_add(float *,float " - "*,float *,int)"), - _A("<< CUDA Device >>
add(float,float)"), "")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "vector_square_add(float *,float *,float *,int)", + ""}, // + {"vector_square_add(float *,float *,float *,int)", + "square(float)", ""}, // + {"vector_square_add(float *,float *,float *,int)", + "square(float)", ""}, // + {"vector_square_add(float *,float *,float *,int)", + "add(float,float)", ""}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20050/test_case.h b/tests/t20050/test_case.h index 935f3e8a..33d0b9db 100644 --- a/tests/t20050/test_case.h +++ b/tests/t20050/test_case.h @@ -16,65 +16,27 @@ * limitations under the License. */ -TEST_CASE("t20050", "[test-case][sequence]") +TEST_CASE("t20050") { - auto [config, db] = load_config("t20050"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20050_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20050", "t20050_sequence"); - REQUIRE(diagram->name == "t20050_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsFileParticipant(src, "t20050.cu")); - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20050_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all calls exist - REQUIRE_THAT(src, - HasCall(_A("t20050.cu"), _A("t20050.cu"), - "<< CUDA Kernel >>\\\\nvector_square_add(float *,float *,float " - "*,int)")); - REQUIRE_THAT(src, - HasCall(_A("t20050.cu"), _A("t20050.cu"), - "<< CUDA Device >>\\\\nsquare(float)")); - REQUIRE_THAT(src, - HasCall(_A("t20050.cu"), _A("t20050.cu"), - "<< CUDA Device >>\\\\nadd(float,float)")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("t20050.cu"), _A("t20050.cu"), - "<< CUDA Kernel >>
vector_square_add(float *,float *,float " - "*,int)")); - REQUIRE_THAT(src, - HasCall(_A("t20050.cu"), _A("t20050.cu"), - "<< CUDA Device >>
square(float)")); - REQUIRE_THAT(src, - HasCall(_A("t20050.cu"), _A("t20050.cu"), - "<< CUDA Device >>
add(float,float)")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(MessageOrder(src, + { + // + {Entrypoint{}, "t20050.cu", "tmain()"}, // + {"t20050.cu", "t20050.cu", + "vector_square_add(float *,float *,float *,int)", + CUDAKernel{}}, // + {"t20050.cu", "t20050.cu", "square(float)", CUDADevice{}}, // + {"t20050.cu", "t20050.cu", "square(float)", CUDADevice{}}, // + {"t20050.cu", "t20050.cu", "add(float,float)", + CUDADevice{}}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20051/test_case.h b/tests/t20051/test_case.h index 0c3806f0..838536bd 100644 --- a/tests/t20051/test_case.h +++ b/tests/t20051/test_case.h @@ -16,66 +16,21 @@ * limitations under the License. */ -TEST_CASE("t20051", "[test-case][sequence]") +TEST_CASE("t20051") { - auto [config, db] = load_config("t20051"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20051_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20051", "t20051_sequence"); - REQUIRE(diagram->name == "t20051_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!IsFileParticipant(src, "t20051.cu")); - auto model = generate_sequence_diagram(*db, diagram); - - REQUIRE(model->name() == "t20051_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("vector_square_add(float *,float *,float *,int)"), "")); - REQUIRE_THAT(src, - !HasCall(_A("vector_square_add(float *,float *,float *,int)"), - _A("square(float)"), "")); - REQUIRE_THAT(src, - !HasCall(_A("vector_square_add(float *,float *,float *,int)"), - _A("add(float,float)"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("<< CUDA Kernel >>
vector_square_add(float *,float " - "*,float *,int)"), - "")); - REQUIRE_THAT(src, - !HasCall(_A("<< CUDA Kernel >>
vector_square_add(float *,float " - "*,float *,int)"), - _A("<< CUDA Device >>
square(float)"), "")); - REQUIRE_THAT(src, - !HasCall(_A("<< CUDA Kernel >>
vector_square_add(float *,float " - "*,float *,int)"), - _A("<< CUDA Device >>
add(float,float)"), "")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "vector_square_add(float *,float *,float *,int)", + ""}, // + })); + }); } \ No newline at end of file diff --git a/tests/t20052/test_case.h b/tests/t20052/test_case.h index 60c38e60..24ef4fe2 100644 --- a/tests/t20052/test_case.h +++ b/tests/t20052/test_case.h @@ -16,161 +16,48 @@ * limitations under the License. */ -TEST_CASE("t20052", "[test-case][sequence]") +TEST_CASE("t20052") { - auto [config, db] = load_config("t20052"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20052_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20052", "t20052_sequence"); - REQUIRE(diagram->name == "t20052_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!IsFileParticipant(src, "t20052.cu")); - auto model = generate_sequence_diagram(*db, diagram); + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "A", "a()"}, // + {"A", "A", "aa()"}, // + {"A", "A", "aaa()"}, // - REQUIRE(model->name() == "t20052_sequence"); + {"tmain()", "B", "b()"}, // + {"B", "B", "bb()"}, // + {"B", "B", "bbb()"}, // - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); + {"tmain()", "C", "c()"}, // + {"C", "C", "cc()"}, // + {"C", "C", "ccc()"}, // - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + {"tmain()", "A", "a()"}, // + {"A", "A", "aa()"}, // + {"A", "A", "aaa()"}, // - // Check if all calls exist - REQUIRE_THAT(src, - !HasCall(_A("tmain()"), _A("tmain()::(lambda t20052.cc:67:20)"), - "operator()() const")); - REQUIRE_THAT(src, - !HasCall(_A("tmain()::(lambda t20052.cc:67:20)"), _A("A"), "a()")); + {"tmain()", "B", "b()"}, // + {"B", "B", "bb()"}, // + {"B", "B", "bbb()"}, // - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "aa()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "aaa()")); + {"tmain()", "R<(lambda at t20052.cc:86:9)>", + "R((lambda at t20052.cc:86:9) &&)"}, // - REQUIRE_THAT(src, - !HasCall(_A("tmain()::(lambda t20052.cc:67:20)"), _A("B"), "b()")); + {"tmain()", "R<(lambda at t20052.cc:86:9)>", "r()"}, // + {"R<(lambda at t20052.cc:86:9)>", "C", "c()"}, // + {"C", "C", "cc()"}, // + {"C", "C", "ccc()"}, // - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "bb()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "bbb()")); - - REQUIRE_THAT(src, - !HasCall(_A("tmain()::(lambda t20052.cc:80:20)"), _A("C"), "c()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("C"), "c()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "cc()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "ccc()")); - - REQUIRE_THAT(src, - !HasCall(_A("tmain()::(lambda t20052.cc:80:20)"), - _A("tmain()::(lambda t20052.cc:67:20)"), "operator()() const")); - - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "ccc()")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("R<(lambda at t20052.cc:86:9)>"), - "R((lambda at t20052.cc:86:9) &&)")); - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("R<(lambda at t20052.cc:86:9)>"), "r()")); - REQUIRE_THAT(src, - !HasCall(_A("R<(lambda at t20052.cc:86:9)>"), - _A("tmain()::(lambda t20052.cc:86:9)"), "operator()() const")); - - REQUIRE_THAT( - src, HasCall(_A("R<(lambda at t20052.cc:86:9)>"), _A("C"), "c()")); - - REQUIRE_THAT(src, - !HasCall(_A("tmain()"), _A("tmain()::(lambda t20052.cc:94:9)"), - "operator()(auto) const")); - REQUIRE_THAT(src, - !HasCall(_A("tmain()::(lambda t20052.cc:94:9)"), _A("D"), - "add5(int) const")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("D"), "add5(int) const")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - std::vector messages = { - FindMessage(j, "tmain()", "A", "a()"), - FindMessage(j, "A", "A", "aa()"), - FindMessage(j, "A", "A", "aaa()"), - FindMessage(j, "tmain()", "B", "b()"), - FindMessage(j, "B", "B", "bb()"), - FindMessage(j, "B", "B", "bbb()"), - FindMessage(j, "tmain()", "C", "c()"), - FindMessage(j, "C", "C", "cc()"), - FindMessage(j, "C", "C", "ccc()"), - FindMessage(j, "tmain()", "R<(lambda at t20052.cc:86:9)>", "r()"), - FindMessage(j, "R<(lambda at t20052.cc:86:9)>", "C", "c()"), - }; - - REQUIRE(std::is_sorted(messages.begin(), messages.end())); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::SequenceDiagramAliasMatcher _A(src); - using mermaid::HasCall; - - REQUIRE_THAT(src, - !HasCall(_A("tmain()"), _A("tmain()::(lambda t20052.cc:67:20)"), - "operator()() const")); - REQUIRE_THAT(src, - !HasCall(_A("tmain()::(lambda t20052.cc:67:20)"), _A("A"), "a()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "aa()")); - REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "aaa()")); - - REQUIRE_THAT(src, - !HasCall(_A("tmain()::(lambda t20052.cc:67:20)"), _A("B"), "b()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("B"), "b()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "bb()")); - REQUIRE_THAT(src, HasCall(_A("B"), _A("B"), "bbb()")); - - REQUIRE_THAT(src, - !HasCall(_A("tmain()::(lambda t20052.cc:80:20)"), _A("C"), "c()")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("C"), "c()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "cc()")); - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "ccc()")); - - REQUIRE_THAT(src, - !HasCall(_A("tmain()::(lambda t20052.cc:80:20)"), - _A("tmain()::(lambda t20052.cc:67:20)"), "operator()() const")); - - REQUIRE_THAT(src, HasCall(_A("C"), _A("C"), "ccc()")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("R<(lambda at t20052.cc:86:9)>"), - "R((lambda at t20052.cc:86:9) &&)")); - REQUIRE_THAT(src, - HasCall(_A("tmain()"), _A("R<(lambda at t20052.cc:86:9)>"), "r()")); - REQUIRE_THAT(src, - !HasCall(_A("R<(lambda at t20052.cc:86:9)>"), - _A("tmain()::(lambda t20052.cc:86:9)"), "operator()() const")); - - REQUIRE_THAT( - src, HasCall(_A("R<(lambda at t20052.cc:86:9)>"), _A("C"), "c()")); - - REQUIRE_THAT(src, - !HasCall(_A("tmain()"), _A("tmain()::(lambda t20052.cc:94:9)"), - "operator()(auto) const")); - REQUIRE_THAT(src, - !HasCall(_A("tmain()::(lambda t20052.cc:94:9)"), _A("D"), - "add5(int) const")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("D"), "add5(int) const")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", "D", "add5(int) const"} // + })); + }); } \ No newline at end of file diff --git a/tests/t20053/test_case.h b/tests/t20053/test_case.h index 29dab3e6..a3b54a9a 100644 --- a/tests/t20053/test_case.h +++ b/tests/t20053/test_case.h @@ -16,55 +16,28 @@ * limitations under the License. */ -TEST_CASE("t20053", "[test-case][sequence]") +TEST_CASE("t20053") { - auto [config, db] = load_config("t20053"); + using namespace clanguml::test; - auto diagram = config.diagrams["t20053_sequence"]; + auto [config, db, diagram, model] = + CHECK_SEQUENCE_MODEL("t20053", "t20053_sequence"); - REQUIRE(diagram->name == "t20053_sequence"); + CHECK_SEQUENCE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(!IsFileParticipant(src, "t20053.cu")); - auto model = generate_sequence_diagram(*db, diagram); + REQUIRE(MessageOrder(src, + { + // + {"tmain()", "a2(int)", ""}, // - REQUIRE(model->name() == "t20053_sequence"); - - { - auto src = generate_sequence_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("a2(int)"), "")); - - REQUIRE_THAT(src, - HasCall(_A("tmain()"), - _A("a1<(lambda at t20053.cc:23:9)>((lambda at t20053.cc:23:9) " - "&&)"), - "")); - - REQUIRE_THAT(src, - HasCall(_A("a1<(lambda at t20053.cc:23:9)>((lambda at " - "t20053.cc:23:9) &&)"), - _A("a3(int)"), "")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_sequence_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_sequence_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {"tmain()", + "a1<(lambda at t20053.cc:23:9)>((lambda at t20053.cc:23:9) " + "&&)", + ""}, // + {"a1<(lambda at t20053.cc:23:9)>((lambda at t20053.cc:23:9) " + "&&)", + "a3(int)", ""}, // + })); + }); } \ No newline at end of file diff --git a/tests/t30001/test_case.h b/tests/t30001/test_case.h index 4772e727..80e3e4f2 100644 --- a/tests/t30001/test_case.h +++ b/tests/t30001/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t30001/test_case.cc + * tests/t30001/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,116 +16,42 @@ * limitations under the License. */ -TEST_CASE("t30001", "[test-case][package]") +TEST_CASE("t30001") { - auto [config, db] = load_config("t30001"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30001_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30001", "t30001_package"); - REQUIRE(diagram->name == "t30001_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(HasTitle(src, "Basic package diagram example")); - auto model = generate_package_diagram(*db, diagram); + REQUIRE(!IsNamespacePackage(src, "clanguml"s)); + REQUIRE(!IsNamespacePackage(src, "t30001"s)); + REQUIRE(IsNamespacePackage(src, "A"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "AAA"s)); + REQUIRE(IsNamespacePackage(src, "B"s, "AA"s, "AAA"s)); + REQUIRE(IsNamespacePackage(src, "B"s, "AA"s, "BBB"s)); + REQUIRE(IsNamespacePackage(src, "B"s, "BB"s)); + REQUIRE(IsNamespacePackage(src, "B"s)); - REQUIRE(model->name() == "t30001_package"); + REQUIRE( + HasNote(src, "AA", "top", "This is namespace AA in namespace A")); - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); + REQUIRE(HasLink(src, "AAA", + fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" + "t30001/t30001.cc#L6", + clanguml::util::get_git_commit()), + "AAA")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(HasLink(src, "BBB", + fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" + "t30001/t30001.cc#L8", + clanguml::util::get_git_commit()), + "BBB")); - REQUIRE_THAT(src, HasTitle("Basic package diagram example")); - - REQUIRE_THAT(src, IsPackage("A")); - REQUIRE_THAT(src, IsPackage("AAA")); - REQUIRE_THAT(src, IsPackage("AAA")); - - // TODO: Fix _A() to handle fully qualified names, right - // now it only finds the first element with unqualified - // name match - REQUIRE_THAT(src, - HasNote(_A("AA"), "top", "This is namespace AA in namespace A")); - - REQUIRE_THAT(src, - HasLink(_A("AAA"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t30001/t30001.cc#L6", - clanguml::util::get_git_commit()), - "AAA")); - - REQUIRE_THAT(src, - HasLink(_A("BBB"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t30001/t30001.cc#L8", - clanguml::util::get_git_commit()), - "BBB")); - - REQUIRE_THAT(src, HasComment("t30001 test diagram of type package")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(HasTitle(j, "Basic package diagram example")); - - REQUIRE(!IsNamespacePackage(j, "clanguml"s)); - REQUIRE(!IsNamespacePackage(j, "t30001"s)); - REQUIRE(IsNamespacePackage(j, "A"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "AAA"s)); - REQUIRE(IsNamespacePackage(j, "B"s, "AA"s, "AAA"s)); - REQUIRE(IsNamespacePackage(j, "B"s, "AA"s, "BBB"s)); - REQUIRE(IsNamespacePackage(j, "B"s, "BB"s)); - REQUIRE(IsNamespacePackage(j, "B"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - - using mermaid::HasComment; - using mermaid::HasLink; - using mermaid::HasPackageNote; - using mermaid::HasTitle; - using mermaid::IsPackage; - - REQUIRE_THAT(src, HasTitle("Basic package diagram example")); - - REQUIRE_THAT(src, IsPackage(_A("A"))); - REQUIRE_THAT(src, IsPackage(_A("AAA"))); - REQUIRE_THAT(src, IsPackage(_A("AAA"))); - - // TODO: Fix _A() to handle fully qualified names, right - // now it only finds the first element with unqualified - // name match - REQUIRE_THAT(src, - HasPackageNote( - _A("AA"), "top", "This is namespace AA in namespace A")); - - REQUIRE_THAT(src, - HasLink(_A("AAA"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t30001/t30001.cc#L6", - clanguml::util::get_git_commit()), - "AAA")); - - REQUIRE_THAT(src, - HasLink(_A("BBB"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t30001/t30001.cc#L8", - clanguml::util::get_git_commit()), - "BBB")); - - REQUIRE_THAT(src, HasComment("t30001 test diagram of type package")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(HasComment(src, "t30001 test diagram of type package")); + }); } diff --git a/tests/t30002/test_case.h b/tests/t30002/test_case.h index 908402ae..bc0badda 100644 --- a/tests/t30002/test_case.h +++ b/tests/t30002/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t30002/test_case.cc + * tests/t30002/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,158 +16,54 @@ * limitations under the License. */ -TEST_CASE("t30002", "[test-case][package]") +TEST_CASE("t30002") { - auto [config, db] = load_config("t30002"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30002_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30002", "t30002_package"); - REQUIRE(diagram->name == "t30002_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A1"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A2"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A3"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A4"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A5"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A6"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A7"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A8"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A9"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A10"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A11"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A12"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A13"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A14"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A15"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A16"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A17"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "A18"s)); - auto model = generate_package_diagram(*db, diagram); + REQUIRE(IsNamespacePackage(src, "B"s, "BB"s, "BBB"s)); - REQUIRE(model->name() == "t30002_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsPackage("A1")); - REQUIRE_THAT(src, IsPackage("A2")); - REQUIRE_THAT(src, IsPackage("A3")); - REQUIRE_THAT(src, IsPackage("A4")); - REQUIRE_THAT(src, IsPackage("A5")); - REQUIRE_THAT(src, IsPackage("A6")); - REQUIRE_THAT(src, IsPackage("A7")); - REQUIRE_THAT(src, IsPackage("A8")); - REQUIRE_THAT(src, IsPackage("A9")); - REQUIRE_THAT(src, IsPackage("A11")); - REQUIRE_THAT(src, IsPackage("A12")); - REQUIRE_THAT(src, IsPackage("A13")); - REQUIRE_THAT(src, IsPackage("A14")); - REQUIRE_THAT(src, IsPackage("A15")); - REQUIRE_THAT(src, IsPackage("A16")); - REQUIRE_THAT(src, IsPackage("A17")); - REQUIRE_THAT(src, IsPackage("A18")); - - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A1"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A2"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A3"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A4"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A5"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A6"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A7"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A8"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A9"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A10"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A11"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A12"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A13"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A14"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A15"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A16"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A17"))); - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("A18"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A1"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A2"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A3"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A4"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A5"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A6"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A7"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A8"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A9"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A10"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A11"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A12"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A13"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A14"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A15"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A16"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A17"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "A18"s)); - - REQUIRE(IsNamespacePackage(j, "B"s, "BB"s, "BBB"s)); - - REQUIRE(IsDependency(j, "BBB", "A1")); - REQUIRE(IsDependency(j, "BBB", "A2")); - REQUIRE(IsDependency(j, "BBB", "A3")); - REQUIRE(IsDependency(j, "BBB", "A4")); - REQUIRE(IsDependency(j, "BBB", "A5")); - REQUIRE(IsDependency(j, "BBB", "A6")); - REQUIRE(IsDependency(j, "BBB", "A7")); - REQUIRE(IsDependency(j, "BBB", "A8")); - REQUIRE(IsDependency(j, "BBB", "A9")); - REQUIRE(IsDependency(j, "BBB", "A10")); - REQUIRE(IsDependency(j, "BBB", "A11")); - REQUIRE(IsDependency(j, "BBB", "A12")); - REQUIRE(IsDependency(j, "BBB", "A13")); - REQUIRE(IsDependency(j, "BBB", "A14")); - REQUIRE(IsDependency(j, "BBB", "A15")); - REQUIRE(IsDependency(j, "BBB", "A16")); - REQUIRE(IsDependency(j, "BBB", "A17")); - REQUIRE(IsDependency(j, "BBB", "A18")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - using mermaid::IsPackageDependency; - - REQUIRE_THAT(src, IsPackage(_A("A1"))); - REQUIRE_THAT(src, IsPackage(_A("A2"))); - REQUIRE_THAT(src, IsPackage(_A("A3"))); - REQUIRE_THAT(src, IsPackage(_A("A4"))); - REQUIRE_THAT(src, IsPackage(_A("A5"))); - REQUIRE_THAT(src, IsPackage(_A("A6"))); - REQUIRE_THAT(src, IsPackage(_A("A7"))); - REQUIRE_THAT(src, IsPackage(_A("A8"))); - REQUIRE_THAT(src, IsPackage(_A("A9"))); - REQUIRE_THAT(src, IsPackage(_A("A11"))); - REQUIRE_THAT(src, IsPackage(_A("A12"))); - REQUIRE_THAT(src, IsPackage(_A("A13"))); - REQUIRE_THAT(src, IsPackage(_A("A14"))); - REQUIRE_THAT(src, IsPackage(_A("A15"))); - REQUIRE_THAT(src, IsPackage(_A("A16"))); - REQUIRE_THAT(src, IsPackage(_A("A17"))); - REQUIRE_THAT(src, IsPackage(_A("A18"))); - - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A1"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A2"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A3"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A4"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A5"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A6"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A7"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A8"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A9"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A10"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A11"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A12"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A13"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A14"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A15"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A16"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A17"))); - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("A18"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "BBB", "A1")); + REQUIRE(IsDependency(src, "BBB", "A2")); + REQUIRE(IsDependency(src, "BBB", "A3")); + REQUIRE(IsDependency(src, "BBB", "A4")); + REQUIRE(IsDependency(src, "BBB", "A5")); + REQUIRE(IsDependency(src, "BBB", "A6")); + REQUIRE(IsDependency(src, "BBB", "A7")); + REQUIRE(IsDependency(src, "BBB", "A8")); + REQUIRE(IsDependency(src, "BBB", "A9")); + REQUIRE(IsDependency(src, "BBB", "A10")); + REQUIRE(IsDependency(src, "BBB", "A11")); + REQUIRE(IsDependency(src, "BBB", "A12")); + REQUIRE(IsDependency(src, "BBB", "A13")); + REQUIRE(IsDependency(src, "BBB", "A14")); + REQUIRE(IsDependency(src, "BBB", "A15")); + REQUIRE(IsDependency(src, "BBB", "A16")); + REQUIRE(IsDependency(src, "BBB", "A17")); + REQUIRE(IsDependency(src, "BBB", "A18")); + }); } diff --git a/tests/t30003/test_case.h b/tests/t30003/test_case.h index 4b9f5863..841e14b4 100644 --- a/tests/t30003/test_case.h +++ b/tests/t30003/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t30003/test_case.cc + * tests/t30003/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,69 +16,23 @@ * limitations under the License. */ -TEST_CASE("t30003", "[test-case][package]") +TEST_CASE("t30003") { - auto [config, db] = load_config("t30003"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30003_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30003", "t30003_package"); - REQUIRE(diagram->name == "t30003_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsNamespacePackage(src, "ns1"s)); + REQUIRE(IsNamespacePackage(src, "ns1"s, "ns2_v1_0_0"s)); + REQUIRE(IsNamespacePackage(src, "ns1"s, "ns2_v0_9_0"s)); + REQUIRE(IsNamespacePackage(src, "ns3"s)); + REQUIRE(IsNamespacePackage(src, "ns3"s, "ns1"s)); + REQUIRE(IsNamespacePackage(src, "ns3"s, "ns1"s, "ns2"s)); - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30003_package"); - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsPackage("ns1")); - REQUIRE_THAT(src, IsPackage("ns2")); - REQUIRE_THAT(src, IsPackage("ns3")); - REQUIRE_THAT(src, IsPackage("ns2_v1_0_0")); - REQUIRE_THAT(src, IsPackage("ns2_v0_9_0")); - - REQUIRE_THAT(src, IsDeprecated(_A("ns2_v0_9_0"))); - REQUIRE_THAT(src, IsDeprecated(_A("ns3"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsNamespacePackage(j, "ns1"s)); - REQUIRE(IsNamespacePackage(j, "ns1"s, "ns2_v1_0_0"s)); - REQUIRE(IsNamespacePackage(j, "ns1"s, "ns2_v0_9_0"s)); - REQUIRE(IsNamespacePackage(j, "ns3"s)); - REQUIRE(IsNamespacePackage(j, "ns3"s, "ns1"s)); - REQUIRE(IsNamespacePackage(j, "ns3"s, "ns1"s, "ns2"s)); - - REQUIRE(IsDeprecated(j, "ns2_v0_9_0")); - REQUIRE(IsDeprecated(j, "ns3")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - - REQUIRE_THAT(src, IsPackage(_A("ns1"))); - REQUIRE_THAT(src, IsPackage(_A("ns2"))); - REQUIRE_THAT(src, IsPackage(_A("ns3"))); - REQUIRE_THAT(src, IsPackage(_A("ns2_v1_0_0"))); - REQUIRE_THAT(src, IsPackage(_A("ns2_v0_9_0"))); - - // REQUIRE_THAT(src, IsDeprecated(_A("ns2_v0_9_0"))); - // REQUIRE_THAT(src, IsDeprecated(_A("ns3"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDeprecated(src, "ns2_v0_9_0")); + REQUIRE(IsDeprecated(src, "ns3")); + }); } diff --git a/tests/t30004/test_case.h b/tests/t30004/test_case.h index bd66c760..91c49361 100644 --- a/tests/t30004/test_case.h +++ b/tests/t30004/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t30004/test_case.cc + * tests/t30004/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,61 +16,20 @@ * limitations under the License. */ -TEST_CASE("t30004", "[test-case][package]") +TEST_CASE("t30004") { - auto [config, db] = load_config("t30004"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30004_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30004", "t30004_package"); - REQUIRE(diagram->name == "t30004_package"); - - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30004_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsPackage("AAA")); - REQUIRE_THAT(src, IsPackage("BBB")); - REQUIRE_THAT(src, IsPackage("CCC")); - REQUIRE_THAT(src, !IsPackage("DDD")); - REQUIRE_THAT(src, IsPackage("EEE")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsNamespacePackage(j, "A"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AAA"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "BBB"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "CCC"s)); - REQUIRE(!IsNamespacePackage(j, "A"s, "DDD"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "EEE"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - - REQUIRE_THAT(src, IsPackage(_A("AAA"))); - REQUIRE_THAT(src, IsPackage(_A("BBB"))); - REQUIRE_THAT(src, IsPackage(_A("CCC"))); - REQUIRE_THAT(src, !IsPackage(_A("DDD"))); - REQUIRE_THAT(src, IsPackage(_A("EEE"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsNamespacePackage(src, "A"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AAA"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "BBB"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "CCC"s)); + REQUIRE(!IsNamespacePackage(src, "A"s, "DDD"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "EEE"s)); + }); } diff --git a/tests/t30005/test_case.h b/tests/t30005/test_case.h index 57248548..055f8359 100644 --- a/tests/t30005/test_case.h +++ b/tests/t30005/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t30005/test_case.cc + * tests/t30005/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,71 +16,26 @@ * limitations under the License. */ -TEST_CASE("t30005", "[test-case][package]") +TEST_CASE("t30005") { - auto [config, db] = load_config("t30005"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30005_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30005", "t30005_package"); - REQUIRE(diagram->name == "t30005_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsNamespacePackage(src, "A"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s, "AAA"s)); + REQUIRE(IsNamespacePackage(src, "B"s)); + REQUIRE(IsNamespacePackage(src, "B"s, "BB"s)); + REQUIRE(IsNamespacePackage(src, "B"s, "BB"s, "BBB"s)); + REQUIRE(IsNamespacePackage(src, "C"s)); + REQUIRE(IsNamespacePackage(src, "C"s, "CC"s)); + REQUIRE(IsNamespacePackage(src, "C"s, "CC"s, "CCC"s)); - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30005_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsPackage("AAA")); - REQUIRE_THAT(src, IsPackage("BBB")); - REQUIRE_THAT(src, IsPackage("CCC")); - - REQUIRE_THAT(src, IsDependency(_A("BBB"), _A("AAA"))); - REQUIRE_THAT(src, IsDependency(_A("CCC"), _A("AAA"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsNamespacePackage(j, "A"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s, "AAA"s)); - REQUIRE(IsNamespacePackage(j, "B"s)); - REQUIRE(IsNamespacePackage(j, "B"s, "BB"s)); - REQUIRE(IsNamespacePackage(j, "B"s, "BB"s, "BBB"s)); - REQUIRE(IsNamespacePackage(j, "C"s)); - REQUIRE(IsNamespacePackage(j, "C"s, "CC"s)); - REQUIRE(IsNamespacePackage(j, "C"s, "CC"s, "CCC"s)); - - REQUIRE(IsDependency(j, "BBB", "AAA")); - REQUIRE(IsDependency(j, "CCC", "AAA")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - using mermaid::IsPackageDependency; - - REQUIRE_THAT(src, IsPackage(_A("AAA"))); - REQUIRE_THAT(src, IsPackage(_A("BBB"))); - REQUIRE_THAT(src, IsPackage(_A("CCC"))); - - REQUIRE_THAT(src, IsPackageDependency(_A("BBB"), _A("AAA"))); - REQUIRE_THAT(src, IsPackageDependency(_A("CCC"), _A("AAA"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "BBB", "AAA")); + REQUIRE(IsDependency(src, "CCC", "AAA")); + }); } diff --git a/tests/t30006/test_case.h b/tests/t30006/test_case.h index 6201fa50..b71807cb 100644 --- a/tests/t30006/test_case.h +++ b/tests/t30006/test_case.h @@ -16,64 +16,20 @@ * limitations under the License. */ -TEST_CASE("t30006", "[test-case][package]") +TEST_CASE("t30006") { - auto [config, db] = load_config("t30006"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30006_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30006", "t30006_package"); - REQUIRE(diagram->name == "t30006_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsNamespacePackage(src, "A"s)); + REQUIRE(IsNamespacePackage(src, "B"s)); + REQUIRE(IsNamespacePackage(src, "C"s)); - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30006_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsPackage("A")); - REQUIRE_THAT(src, IsPackage("B")); - REQUIRE_THAT(src, IsPackage("C")); - - REQUIRE_THAT(src, IsDependency(_A("A"), _A("B"))); - REQUIRE_THAT(src, IsDependency(_A("A"), _A("C"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsNamespacePackage(j, "A"s)); - REQUIRE(IsNamespacePackage(j, "B"s)); - REQUIRE(IsNamespacePackage(j, "C"s)); - - REQUIRE(IsDependency(j, "A", "B")); - REQUIRE(IsDependency(j, "A", "C")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - using mermaid::IsPackageDependency; - - REQUIRE_THAT(src, IsPackage(_A("A"))); - REQUIRE_THAT(src, IsPackage(_A("B"))); - REQUIRE_THAT(src, IsPackage(_A("C"))); - - REQUIRE_THAT(src, IsPackageDependency(_A("A"), _A("B"))); - REQUIRE_THAT(src, IsPackageDependency(_A("A"), _A("C"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "A", "B")); + REQUIRE(IsDependency(src, "A", "C")); + }); } diff --git a/tests/t30007/test_case.h b/tests/t30007/test_case.h index 653212db..3832c181 100644 --- a/tests/t30007/test_case.h +++ b/tests/t30007/test_case.h @@ -16,68 +16,24 @@ * limitations under the License. */ -TEST_CASE("t30007", "[test-case][package]") +TEST_CASE("t30007") { - auto [config, db] = load_config("t30007"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30007_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30007", "t30007_package"); - REQUIRE(diagram->name == "t30007_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsNamespacePackage(src, "A"s)); + REQUIRE(IsNamespacePackage(src, "A"s, "AA"s)); + REQUIRE(IsNamespacePackage(src, "B"s)); + REQUIRE(IsNamespacePackage(src, "C"s)); - auto model = generate_package_diagram(*db, diagram); + REQUIRE(IsDependency(src, "AA", "B")); + REQUIRE(IsDependency(src, "AA", "C")); - REQUIRE(model->name() == "t30007_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsPackage("A")); - REQUIRE_THAT(src, IsPackage("B")); - REQUIRE_THAT(src, IsPackage("C")); - - REQUIRE_THAT(src, IsDependency(_A("AA"), _A("B"))); - REQUIRE_THAT(src, IsDependency(_A("AA"), _A("C"))); - - REQUIRE_THAT(src, IsLayoutHint(_A("C"), "up", _A("AA"))); - REQUIRE_THAT(src, IsLayoutHint(_A("C"), "left", _A("B"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsNamespacePackage(j, "A"s)); - REQUIRE(IsNamespacePackage(j, "A"s, "AA"s)); - REQUIRE(IsNamespacePackage(j, "B"s)); - REQUIRE(IsNamespacePackage(j, "C"s)); - - REQUIRE(IsDependency(j, "AA", "B")); - REQUIRE(IsDependency(j, "AA", "C")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - using mermaid::IsPackageDependency; - - REQUIRE_THAT(src, IsPackage(_A("A"))); - REQUIRE_THAT(src, IsPackage(_A("B"))); - REQUIRE_THAT(src, IsPackage(_A("C"))); - - REQUIRE_THAT(src, IsPackageDependency(_A("AA"), _A("B"))); - REQUIRE_THAT(src, IsPackageDependency(_A("AA"), _A("C"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsLayoutHint(src, "C", "up", "AA")); + REQUIRE(IsLayoutHint(src, "C", "left", "B")); + }); } diff --git a/tests/t30008/test_case.h b/tests/t30008/test_case.h index 70f52d6a..95c3d048 100644 --- a/tests/t30008/test_case.h +++ b/tests/t30008/test_case.h @@ -16,91 +16,29 @@ * limitations under the License. */ -TEST_CASE("t30008", "[test-case][package]") +TEST_CASE("t30008") { - auto [config, db] = load_config("t30008"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30008_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30008", "t30008_package"); - REQUIRE(diagram->name == "t30008_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsNamespacePackage(src, "dependants"s, "A"s)); + REQUIRE(IsNamespacePackage(src, "dependants"s, "B"s)); + REQUIRE(IsNamespacePackage(src, "dependants"s, "C"s)); + REQUIRE(!IsNamespacePackage(src, "dependants"s, "X"s)); - auto model = generate_package_diagram(*db, diagram); + REQUIRE(IsDependency(src, "B", "A")); + REQUIRE(IsDependency(src, "C", "B")); - REQUIRE(model->name() == "t30008_package"); + REQUIRE(IsNamespacePackage(src, "dependencies"s, "D"s)); + REQUIRE(IsNamespacePackage(src, "dependencies"s, "E"s)); + REQUIRE(IsNamespacePackage(src, "dependencies"s, "F"s)); + REQUIRE(!IsNamespacePackage(src, "dependencies"s, "Y"s)); - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsPackage("A")); - REQUIRE_THAT(src, IsPackage("B")); - REQUIRE_THAT(src, IsPackage("C")); - REQUIRE_THAT(src, !IsPackage("X")); - - REQUIRE_THAT(src, IsDependency(_A("B"), _A("A"))); - REQUIRE_THAT(src, IsDependency(_A("C"), _A("B"))); - - REQUIRE_THAT(src, IsPackage("D")); - REQUIRE_THAT(src, IsPackage("E")); - REQUIRE_THAT(src, IsPackage("F")); - REQUIRE_THAT(src, !IsPackage("Y")); - - REQUIRE_THAT(src, IsDependency(_A("E"), _A("D"))); - REQUIRE_THAT(src, IsDependency(_A("F"), _A("E"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsNamespacePackage(j, "dependants"s, "A"s)); - REQUIRE(IsNamespacePackage(j, "dependants"s, "B"s)); - REQUIRE(IsNamespacePackage(j, "dependants"s, "C"s)); - REQUIRE(!IsNamespacePackage(j, "dependants"s, "X"s)); - - REQUIRE(IsDependency(j, "B", "A")); - REQUIRE(IsDependency(j, "C", "B")); - - REQUIRE(IsNamespacePackage(j, "dependencies"s, "D"s)); - REQUIRE(IsNamespacePackage(j, "dependencies"s, "E"s)); - REQUIRE(IsNamespacePackage(j, "dependencies"s, "F"s)); - REQUIRE(!IsNamespacePackage(j, "dependencies"s, "Y"s)); - - REQUIRE(IsDependency(j, "E", "D")); - REQUIRE(IsDependency(j, "F", "E")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - using mermaid::IsPackageDependency; - - REQUIRE_THAT(src, IsPackage(_A("A"))); - REQUIRE_THAT(src, IsPackage(_A("B"))); - REQUIRE_THAT(src, IsPackage(_A("C"))); - REQUIRE_THAT(src, !IsPackage(_A("X"))); - - REQUIRE_THAT(src, IsPackageDependency(_A("B"), _A("A"))); - REQUIRE_THAT(src, IsPackageDependency(_A("C"), _A("B"))); - - REQUIRE_THAT(src, IsPackage(_A("D"))); - REQUIRE_THAT(src, IsPackage(_A("E"))); - REQUIRE_THAT(src, IsPackage(_A("F"))); - REQUIRE_THAT(src, !IsPackage(_A("Y"))); - - REQUIRE_THAT(src, IsPackageDependency(_A("E"), _A("D"))); - REQUIRE_THAT(src, IsPackageDependency(_A("F"), _A("E"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "E", "D")); + REQUIRE(IsDependency(src, "F", "E")); + }); } diff --git a/tests/t30009/test_case.h b/tests/t30009/test_case.h index 84600695..6644441a 100644 --- a/tests/t30009/test_case.h +++ b/tests/t30009/test_case.h @@ -16,68 +16,24 @@ * limitations under the License. */ -TEST_CASE("t30009", "[test-case][package]") +TEST_CASE("t30009") { - auto [config, db] = load_config("t30009"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30009_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30009", "t30009_package"); - REQUIRE(diagram->name == "t30009_package"); - - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30009_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all packages exist - REQUIRE_THAT(src, IsPackage("One")); - REQUIRE_THAT(src, IsPackage("Two")); - REQUIRE_THAT(src, IsPackage("A")); - REQUIRE_THAT(src, IsPackage("B")); - REQUIRE_THAT(src, IsPackage("C")); - REQUIRE_THAT(src, IsPackage("D")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsNamespacePackage(j, "One"s)); - REQUIRE(IsNamespacePackage(j, "Two"s)); - REQUIRE(IsNamespacePackage(j, "One"s, "A"s)); - REQUIRE(IsNamespacePackage(j, "One"s, "B"s)); - REQUIRE(IsNamespacePackage(j, "One"s, "C"s)); - REQUIRE(IsNamespacePackage(j, "One"s, "D"s)); - REQUIRE(IsNamespacePackage(j, "Two"s, "A"s)); - REQUIRE(IsNamespacePackage(j, "Two"s, "B"s)); - REQUIRE(IsNamespacePackage(j, "Two"s, "C"s)); - REQUIRE(IsNamespacePackage(j, "Two"s, "D"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - - REQUIRE_THAT(src, IsPackage(_A("One"))); - REQUIRE_THAT(src, IsPackage(_A("Two"))); - REQUIRE_THAT(src, IsPackage(_A("A"))); - REQUIRE_THAT(src, IsPackage(_A("B"))); - REQUIRE_THAT(src, IsPackage(_A("C"))); - REQUIRE_THAT(src, IsPackage(_A("D"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsNamespacePackage(src, "One"s)); + REQUIRE(IsNamespacePackage(src, "Two"s)); + REQUIRE(IsNamespacePackage(src, "One"s, "A"s)); + REQUIRE(IsNamespacePackage(src, "One"s, "B"s)); + REQUIRE(IsNamespacePackage(src, "One"s, "C"s)); + REQUIRE(IsNamespacePackage(src, "One"s, "D"s)); + REQUIRE(IsNamespacePackage(src, "Two"s, "A"s)); + REQUIRE(IsNamespacePackage(src, "Two"s, "B"s)); + REQUIRE(IsNamespacePackage(src, "Two"s, "C"s)); + REQUIRE(IsNamespacePackage(src, "Two"s, "D"s)); + }); } \ No newline at end of file diff --git a/tests/t30010/test_case.h b/tests/t30010/test_case.h index 19d06edf..e48ebbc2 100644 --- a/tests/t30010/test_case.h +++ b/tests/t30010/test_case.h @@ -16,73 +16,24 @@ * limitations under the License. */ -TEST_CASE("t30010", "[test-case][package]") +TEST_CASE("t30010") { - auto [config, db] = load_config("t30010"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30010_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30010", "t30010_package"); - REQUIRE(diagram->name == "t30010_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsDirectoryPackage(src, "app"s)); + REQUIRE(IsDirectoryPackage(src, "libraries"s, "lib1"s)); + REQUIRE(IsDirectoryPackage(src, "libraries"s, "lib2"s)); + REQUIRE(IsDirectoryPackage(src, "libraries"s, "lib3"s)); + REQUIRE(IsDirectoryPackage(src, "libraries"s, "lib4"s)); - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30010_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsPackage("app")); - REQUIRE_THAT(src, IsPackage("libraries")); - REQUIRE_THAT(src, IsPackage("lib1")); - REQUIRE_THAT(src, IsPackage("lib2")); - REQUIRE_THAT(src, !IsPackage("library1")); - REQUIRE_THAT(src, !IsPackage("library2")); - - REQUIRE_THAT(src, IsDependency(_A("app"), _A("lib1"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("lib2"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("lib3"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("lib4"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsDirectoryPackage(j, "app"s)); - REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib1"s)); - REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib2"s)); - REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib3"s)); - REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib4"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - using mermaid::IsPackageDependency; - - REQUIRE_THAT(src, IsPackage(_A("app"))); - REQUIRE_THAT(src, IsPackage(_A("libraries"))); - REQUIRE_THAT(src, IsPackage(_A("lib1"))); - REQUIRE_THAT(src, IsPackage(_A("lib2"))); - REQUIRE_THAT(src, !IsPackage(_A("library1"))); - REQUIRE_THAT(src, !IsPackage(_A("library2"))); - - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("lib1"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("lib2"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("lib3"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("lib4"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "app", "lib1")); + REQUIRE(IsDependency(src, "app", "lib2")); + REQUIRE(IsDependency(src, "app", "lib3")); + REQUIRE(IsDependency(src, "app", "lib4")); + }); } \ No newline at end of file diff --git a/tests/t30011/test_case.h b/tests/t30011/test_case.h index a8adfd0a..70153b43 100644 --- a/tests/t30011/test_case.h +++ b/tests/t30011/test_case.h @@ -16,78 +16,24 @@ * limitations under the License. */ -TEST_CASE("t30011", "[test-case][package]") +TEST_CASE("t30011") { - auto [config, db] = load_config("t30011"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30011_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30011", "t30011_package"); - REQUIRE(diagram->name == "t30011_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsDirectoryPackage(src, "app"s)); + REQUIRE(IsDirectoryPackage(src, "libraries"s, "lib1"s)); + REQUIRE(IsDirectoryPackage(src, "libraries"s, "lib2"s)); + REQUIRE(IsDirectoryPackage(src, "libraries"s, "lib3"s)); + REQUIRE(IsDirectoryPackage(src, "libraries"s, "lib4"s)); - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30011_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsPackage("app")); - REQUIRE_THAT(src, IsPackage("libraries")); - REQUIRE_THAT(src, IsPackage("lib1")); - REQUIRE_THAT(src, IsPackage("lib2")); - REQUIRE_THAT(src, !IsPackage("library1")); - REQUIRE_THAT(src, !IsPackage("library2")); - - REQUIRE_THAT(src, IsDependency(_A("app"), _A("lib1"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("lib2"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("lib3"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("lib4"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsDirectoryPackage(j, "app"s)); - REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib1"s)); - REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib2"s)); - REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib3"s)); - REQUIRE(IsDirectoryPackage(j, "libraries"s, "lib4"s)); - - REQUIRE(IsDependency(j, "app"s, "lib1"s)); - REQUIRE(IsDependency(j, "app"s, "lib2"s)); - REQUIRE(IsDependency(j, "app"s, "lib3"s)); - REQUIRE(IsDependency(j, "app"s, "lib4"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - using mermaid::IsPackageDependency; - - REQUIRE_THAT(src, IsPackage(_A("app"))); - REQUIRE_THAT(src, IsPackage(_A("libraries"))); - REQUIRE_THAT(src, IsPackage(_A("lib1"))); - REQUIRE_THAT(src, IsPackage(_A("lib2"))); - REQUIRE_THAT(src, !IsPackage(_A("library1"))); - REQUIRE_THAT(src, !IsPackage(_A("library2"))); - - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("lib1"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("lib2"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("lib3"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("lib4"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "app", "lib1")); + REQUIRE(IsDependency(src, "app", "lib2")); + REQUIRE(IsDependency(src, "app", "lib3")); + REQUIRE(IsDependency(src, "app", "lib4")); + }); } \ No newline at end of file diff --git a/tests/t30012/test_case.h b/tests/t30012/test_case.h index 1e841adb..1c919c44 100644 --- a/tests/t30012/test_case.h +++ b/tests/t30012/test_case.h @@ -16,62 +16,19 @@ * limitations under the License. */ -TEST_CASE("t30012", "[test-case][package]") +TEST_CASE("t30012") { - auto [config, db] = load_config("t30012"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30012_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30012", "t30012_package"); - REQUIRE(diagram->name == "t30012_package"); - - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30012_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all packages exist - REQUIRE_THAT(src, IsPackage("app")); - REQUIRE_THAT(src, IsPackage("lib1")); - REQUIRE_THAT(src, IsPackage("lib2")); - REQUIRE_THAT(src, IsPackage("mod1")); - REQUIRE_THAT(src, IsPackage("mod2")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsModulePackage(j, "app"s)); - REQUIRE(IsModulePackage(j, "app"s, "lib1"s)); - REQUIRE(IsModulePackage(j, "app"s, "lib1"s, "mod1"s)); - REQUIRE(IsModulePackage(j, "app"s, "lib1"s, "mod2"s)); - REQUIRE(IsModulePackage(j, "app"s, "lib2"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - - REQUIRE_THAT(src, IsPackage(_A("app"))); - REQUIRE_THAT(src, IsPackage(_A("lib1"))); - REQUIRE_THAT(src, IsPackage(_A("lib2"))); - REQUIRE_THAT(src, IsPackage(_A("mod1"))); - REQUIRE_THAT(src, IsPackage(_A("mod2"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsModulePackage(src, "app"s)); + REQUIRE(IsModulePackage(src, "app"s, "lib1"s)); + REQUIRE(IsModulePackage(src, "app"s, "lib1"s, "mod1"s)); + REQUIRE(IsModulePackage(src, "app"s, "lib1"s, "mod2"s)); + REQUIRE(IsModulePackage(src, "app"s, "lib2"s)); + }); } \ No newline at end of file diff --git a/tests/t30013/test_case.h b/tests/t30013/test_case.h index 44b9024f..5a5ac1db 100644 --- a/tests/t30013/test_case.h +++ b/tests/t30013/test_case.h @@ -16,142 +16,52 @@ * limitations under the License. */ -TEST_CASE("t30013", "[test-case][package]") +TEST_CASE("t30013") { - auto [config, db] = load_config("t30013"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30013_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30013", "t30013_package"); - REQUIRE(diagram->name == "t30013_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsModulePackage(src, "app"s)); + REQUIRE(IsModulePackage(src, "mod1"s)); + REQUIRE(IsModulePackage(src, "mod2"s)); + REQUIRE(IsModulePackage(src, "mod3"s)); + REQUIRE(IsModulePackage(src, "mod4"s)); + REQUIRE(IsModulePackage(src, "mod5"s)); + REQUIRE(IsModulePackage(src, "mod6"s)); + REQUIRE(IsModulePackage(src, "mod7"s)); + REQUIRE(IsModulePackage(src, "mod8"s)); + REQUIRE(IsModulePackage(src, "mod9"s)); + REQUIRE(IsModulePackage(src, "mod10"s)); + REQUIRE(IsModulePackage(src, "mod11"s)); + REQUIRE(IsModulePackage(src, "mod12"s)); + REQUIRE(IsModulePackage(src, "mod13"s)); + REQUIRE(IsModulePackage(src, "mod14"s)); + REQUIRE(IsModulePackage(src, "mod15"s)); + REQUIRE(IsModulePackage(src, "mod16"s)); + REQUIRE(IsModulePackage(src, "mod17"s)); + REQUIRE(IsModulePackage(src, "mod18"s)); - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30013_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all packages exist - REQUIRE_THAT(src, IsPackage("app")); - REQUIRE_THAT(src, IsPackage("mod1")); - REQUIRE_THAT(src, IsPackage("mod2")); - REQUIRE_THAT(src, IsPackage("mod3")); - REQUIRE_THAT(src, IsPackage("mod4")); - REQUIRE_THAT(src, IsPackage("mod5")); - REQUIRE_THAT(src, IsPackage("mod6")); - REQUIRE_THAT(src, IsPackage("mod7")); - REQUIRE_THAT(src, IsPackage("mod8")); - REQUIRE_THAT(src, IsPackage("mod9")); - REQUIRE_THAT(src, IsPackage("mod10")); - REQUIRE_THAT(src, IsPackage("mod11")); - REQUIRE_THAT(src, IsPackage("mod12")); - REQUIRE_THAT(src, IsPackage("mod13")); - REQUIRE_THAT(src, IsPackage("mod14")); - REQUIRE_THAT(src, IsPackage("mod15")); - REQUIRE_THAT(src, IsPackage("mod16")); - REQUIRE_THAT(src, IsPackage("mod17")); - REQUIRE_THAT(src, IsPackage("mod18")); - - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod1"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod2"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod3"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod4"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod5"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod6"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod7"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod8"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod9"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod10"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod11"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod12"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod13"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod14"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod15"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod16"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod17"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A("mod18"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - REQUIRE(IsModulePackage(j, "app"s)); - REQUIRE(IsModulePackage(j, "mod1"s)); - REQUIRE(IsModulePackage(j, "mod2"s)); - REQUIRE(IsModulePackage(j, "mod3"s)); - REQUIRE(IsModulePackage(j, "mod4"s)); - REQUIRE(IsModulePackage(j, "mod5"s)); - REQUIRE(IsModulePackage(j, "mod6"s)); - REQUIRE(IsModulePackage(j, "mod7"s)); - REQUIRE(IsModulePackage(j, "mod8"s)); - REQUIRE(IsModulePackage(j, "mod9"s)); - REQUIRE(IsModulePackage(j, "mod10"s)); - REQUIRE(IsModulePackage(j, "mod11"s)); - REQUIRE(IsModulePackage(j, "mod12"s)); - REQUIRE(IsModulePackage(j, "mod13"s)); - REQUIRE(IsModulePackage(j, "mod14"s)); - REQUIRE(IsModulePackage(j, "mod15"s)); - REQUIRE(IsModulePackage(j, "mod16"s)); - REQUIRE(IsModulePackage(j, "mod17"s)); - REQUIRE(IsModulePackage(j, "mod18"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - using mermaid::IsPackageDependency; - - REQUIRE_THAT(src, IsPackage(_A("app"))); - REQUIRE_THAT(src, IsPackage(_A("mod1"))); - REQUIRE_THAT(src, IsPackage(_A("mod2"))); - REQUIRE_THAT(src, IsPackage(_A("mod3"))); - REQUIRE_THAT(src, IsPackage(_A("mod4"))); - REQUIRE_THAT(src, IsPackage(_A("mod5"))); - REQUIRE_THAT(src, IsPackage(_A("mod6"))); - REQUIRE_THAT(src, IsPackage(_A("mod7"))); - REQUIRE_THAT(src, IsPackage(_A("mod8"))); - REQUIRE_THAT(src, IsPackage(_A("mod9"))); - REQUIRE_THAT(src, IsPackage(_A("mod10"))); - REQUIRE_THAT(src, IsPackage(_A("mod11"))); - REQUIRE_THAT(src, IsPackage(_A("mod12"))); - REQUIRE_THAT(src, IsPackage(_A("mod13"))); - REQUIRE_THAT(src, IsPackage(_A("mod14"))); - REQUIRE_THAT(src, IsPackage(_A("mod15"))); - REQUIRE_THAT(src, IsPackage(_A("mod16"))); - REQUIRE_THAT(src, IsPackage(_A("mod17"))); - REQUIRE_THAT(src, IsPackage(_A("mod18"))); - - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod1"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod2"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod3"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod4"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod5"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod6"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod7"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod8"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod9"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod10"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod11"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod12"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod13"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod14"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod15"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod16"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod17"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A("mod18"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "app", "mod1")); + REQUIRE(IsDependency(src, "app", "mod2")); + REQUIRE(IsDependency(src, "app", "mod3")); + REQUIRE(IsDependency(src, "app", "mod4")); + REQUIRE(IsDependency(src, "app", "mod5")); + REQUIRE(IsDependency(src, "app", "mod6")); + REQUIRE(IsDependency(src, "app", "mod7")); + REQUIRE(IsDependency(src, "app", "mod8")); + REQUIRE(IsDependency(src, "app", "mod9")); + REQUIRE(IsDependency(src, "app", "mod10")); + REQUIRE(IsDependency(src, "app", "mod11")); + REQUIRE(IsDependency(src, "app", "mod12")); + REQUIRE(IsDependency(src, "app", "mod13")); + REQUIRE(IsDependency(src, "app", "mod14")); + REQUIRE(IsDependency(src, "app", "mod15")); + REQUIRE(IsDependency(src, "app", "mod16")); + REQUIRE(IsDependency(src, "app", "mod17")); + REQUIRE(IsDependency(src, "app", "mod18")); + }); } \ No newline at end of file diff --git a/tests/t30014/test_case.h b/tests/t30014/test_case.h index 06c30eed..e98fee7d 100644 --- a/tests/t30014/test_case.h +++ b/tests/t30014/test_case.h @@ -16,61 +16,19 @@ * limitations under the License. */ -TEST_CASE("t30014", "[test-case][package]") +TEST_CASE("t30014") { - auto [config, db] = load_config("t30014"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30014_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30014", "t30014_package"); - REQUIRE(diagram->name == "t30014_package"); - - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30014_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all packages exist - REQUIRE_THAT(src, IsPackage("app")); - REQUIRE_THAT(src, IsPackage(":lib1")); - REQUIRE_THAT(src, IsPackage(":lib2")); - REQUIRE_THAT(src, IsPackage("mod1")); - REQUIRE_THAT(src, !IsPackage("mod2")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsModulePackage(j, "app"s)); - REQUIRE(IsModulePackage(j, "app"s, ":lib1"s)); - REQUIRE(IsModulePackage(j, "app"s, ":lib2"s)); - REQUIRE(IsModulePackage(j, "app"s, ":lib1"s, "mod1"s)); - REQUIRE(!IsModulePackage(j, "app"s, ":lib1"s, "mod2"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - - REQUIRE_THAT(src, IsPackage(_A("app"))); - REQUIRE_THAT(src, IsPackage(_A(":lib1"))); - REQUIRE_THAT(src, IsPackage(_A(":lib2"))); - REQUIRE_THAT(src, IsPackage(_A("mod1"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsModulePackage(src, "app"s)); + REQUIRE(IsModulePackage(src, "app"s, ":lib1"s)); + REQUIRE(IsModulePackage(src, "app"s, ":lib2"s)); + REQUIRE(IsModulePackage(src, "app"s, ":lib1"s, "mod1"s)); + REQUIRE(!IsModulePackage(src, "app"s, ":lib1"s, "mod2"s)); + }); } \ No newline at end of file diff --git a/tests/t30015/test_case.h b/tests/t30015/test_case.h index 85dc7eab..1cce3c53 100644 --- a/tests/t30015/test_case.h +++ b/tests/t30015/test_case.h @@ -16,146 +16,53 @@ * limitations under the License. */ -TEST_CASE("t30015", "[test-case][package]") +TEST_CASE("t30015") { - auto [config, db] = load_config("t30015"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t30015_package"]; + auto [config, db, diagram, model] = + CHECK_PACKAGE_MODEL("t30015", "t30015_package"); - REQUIRE(diagram->name == "t30015_package"); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsModulePackage(src, "app"s)); + REQUIRE(IsModulePackage(src, "lib1"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod1"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod2"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod3"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod4"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod5"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod6"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod7"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod8"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod9"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod10"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod11"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod12"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod13"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod14"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod15"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod16"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod17"s)); + REQUIRE(IsModulePackage(src, "lib1"s, ":mod18"s)); - auto model = generate_package_diagram(*db, diagram); - - REQUIRE(model->name() == "t30015_package"); - - { - auto src = generate_package_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - // Check if all packages exist - REQUIRE_THAT(src, IsPackage("app")); - REQUIRE_THAT(src, IsPackage("lib1")); - REQUIRE_THAT(src, IsPackage(":mod1")); - REQUIRE_THAT(src, IsPackage(":mod2")); - REQUIRE_THAT(src, IsPackage(":mod3")); - REQUIRE_THAT(src, IsPackage(":mod4")); - REQUIRE_THAT(src, IsPackage(":mod5")); - REQUIRE_THAT(src, IsPackage(":mod6")); - REQUIRE_THAT(src, IsPackage(":mod7")); - REQUIRE_THAT(src, IsPackage(":mod8")); - REQUIRE_THAT(src, IsPackage(":mod9")); - REQUIRE_THAT(src, IsPackage(":mod10")); - REQUIRE_THAT(src, IsPackage(":mod11")); - REQUIRE_THAT(src, IsPackage(":mod12")); - REQUIRE_THAT(src, IsPackage(":mod13")); - REQUIRE_THAT(src, IsPackage(":mod14")); - REQUIRE_THAT(src, IsPackage(":mod15")); - REQUIRE_THAT(src, IsPackage(":mod16")); - REQUIRE_THAT(src, IsPackage(":mod17")); - REQUIRE_THAT(src, IsPackage(":mod18")); - - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod1"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod2"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod3"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod4"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod5"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod6"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod7"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod8"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod9"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod10"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod11"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod12"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod13"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod14"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod15"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod16"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod17"))); - REQUIRE_THAT(src, IsDependency(_A("app"), _A(":mod18"))); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_package_json(diagram, *model); - - using namespace json; - using namespace std::string_literals; - - REQUIRE(IsModulePackage(j, "app"s)); - REQUIRE(IsModulePackage(j, "lib1"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod1"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod2"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod3"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod4"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod5"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod6"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod7"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod8"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod9"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod10"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod11"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod12"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod13"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod14"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod15"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod16"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod17"s)); - REQUIRE(IsModulePackage(j, "lib1"s, ":mod18"s)); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_package_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsPackage; - using mermaid::IsPackageDependency; - - REQUIRE_THAT(src, IsPackage(_A("app"))); - REQUIRE_THAT(src, IsPackage(_A("lib1"))); - REQUIRE_THAT(src, IsPackage(_A(":mod1"))); - REQUIRE_THAT(src, IsPackage(_A(":mod2"))); - REQUIRE_THAT(src, IsPackage(_A(":mod3"))); - REQUIRE_THAT(src, IsPackage(_A(":mod4"))); - REQUIRE_THAT(src, IsPackage(_A(":mod5"))); - REQUIRE_THAT(src, IsPackage(_A(":mod6"))); - REQUIRE_THAT(src, IsPackage(_A(":mod7"))); - REQUIRE_THAT(src, IsPackage(_A(":mod8"))); - REQUIRE_THAT(src, IsPackage(_A(":mod9"))); - REQUIRE_THAT(src, IsPackage(_A(":mod10"))); - REQUIRE_THAT(src, IsPackage(_A(":mod11"))); - REQUIRE_THAT(src, IsPackage(_A(":mod12"))); - REQUIRE_THAT(src, IsPackage(_A(":mod13"))); - REQUIRE_THAT(src, IsPackage(_A(":mod14"))); - REQUIRE_THAT(src, IsPackage(_A(":mod15"))); - REQUIRE_THAT(src, IsPackage(_A(":mod16"))); - REQUIRE_THAT(src, IsPackage(_A(":mod17"))); - REQUIRE_THAT(src, IsPackage(_A(":mod18"))); - - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod1"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod2"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod3"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod4"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod5"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod6"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod7"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod8"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod9"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod10"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod11"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod12"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod13"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod14"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod15"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod16"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod17"))); - REQUIRE_THAT(src, IsPackageDependency(_A("app"), _A(":mod18"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsDependency(src, "app", ":mod1")); + REQUIRE(IsDependency(src, "app", ":mod2")); + REQUIRE(IsDependency(src, "app", ":mod3")); + REQUIRE(IsDependency(src, "app", ":mod4")); + REQUIRE(IsDependency(src, "app", ":mod5")); + REQUIRE(IsDependency(src, "app", ":mod6")); + REQUIRE(IsDependency(src, "app", ":mod7")); + REQUIRE(IsDependency(src, "app", ":mod8")); + REQUIRE(IsDependency(src, "app", ":mod9")); + REQUIRE(IsDependency(src, "app", ":mod10")); + REQUIRE(IsDependency(src, "app", ":mod11")); + REQUIRE(IsDependency(src, "app", ":mod12")); + REQUIRE(IsDependency(src, "app", ":mod13")); + REQUIRE(IsDependency(src, "app", ":mod14")); + REQUIRE(IsDependency(src, "app", ":mod15")); + REQUIRE(IsDependency(src, "app", ":mod16")); + REQUIRE(IsDependency(src, "app", ":mod17")); + REQUIRE(IsDependency(src, "app", ":mod18")); + }); } \ No newline at end of file diff --git a/tests/t40001/test_case.h b/tests/t40001/test_case.h index 1bdef77c..7aa56330 100644 --- a/tests/t40001/test_case.h +++ b/tests/t40001/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t40001/test_case.cc + * tests/t40001/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,101 +16,30 @@ * limitations under the License. */ -TEST_CASE("t40001", "[test-case][include]") +TEST_CASE("t40001") { - auto [config, db] = load_config("t40001"); + using namespace clanguml::test; - auto diagram = config.diagrams["t40001_include"]; + auto [config, db, diagram, model] = + CHECK_INCLUDE_MODEL("t40001", "t40001_include"); - REQUIRE(diagram->name == "t40001_include"); + CHECK_INCLUDE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(HasTitle(src, "Basic include diagram example")); - auto model = generate_include_diagram(*db, diagram); + REQUIRE(IsFolder(src, "include/lib1")); + REQUIRE(IsFile(src, "include/lib1/lib1.h")); + REQUIRE(IsFile(src, "src/t40001.cc")); + REQUIRE(IsFile(src, "include/t40001_include1.h")); - REQUIRE(model->name() == "t40001_include"); + REQUIRE(IsSystemHeader(src, "string")); + REQUIRE(IsSystemHeader(src, "yaml-cpp/yaml.h")); - { - auto src = generate_include_puml(diagram, *model); + REQUIRE(IsHeaderDependency( + src, "src/t40001.cc", "include/t40001_include1.h")); + REQUIRE(IsHeaderDependency( + src, "include/t40001_include1.h", "include/lib1/lib1.h")); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, HasTitle("Basic include diagram example")); - - REQUIRE_THAT(src, IsFolder("lib1")); - REQUIRE_THAT(src, IsFile("lib1.h")); - REQUIRE_THAT(src, IsFile("t40001.cc")); - REQUIRE_THAT(src, IsFile("t40001_include1.h")); - - REQUIRE_THAT(src, IsFile("string")); - REQUIRE_THAT(src, IsFile("yaml-cpp/yaml.h")); - - REQUIRE_THAT( - src, IsAssociation(_A("t40001.cc"), _A("t40001_include1.h"))); - REQUIRE_THAT(src, IsAssociation(_A("t40001_include1.h"), _A("lib1.h"))); - - REQUIRE_THAT(src, IsDependency(_A("t40001_include1.h"), _A("string"))); - - REQUIRE_THAT(src, HasComment("t40001 test diagram of type include")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_include_json(diagram, *model); - - using namespace json; - - REQUIRE(HasTitle(j, "Basic include diagram example")); - - REQUIRE(IsFolder(j, "include")); - REQUIRE(IsFolder(j, "include/lib1")); - REQUIRE(IsFolder(j, "src")); - - REQUIRE(IsHeader(j, "include/lib1/lib1.h")); - REQUIRE(IsHeader(j, "include/t40001_include1.h")); - REQUIRE(IsFile(j, "src/t40001.cc")); - REQUIRE(IsSystemHeader(j, "yaml-cpp/yaml.h")); - - REQUIRE(IsFile(j, "string")); - - REQUIRE(IsAssociation(j, "src/t40001.cc", "include/t40001_include1.h")); - REQUIRE(IsAssociation( - j, "include/t40001_include1.h", "include/lib1/lib1.h")); - REQUIRE(IsDependency(j, "include/t40001_include1.h", "string")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_include_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::HasComment; - using mermaid::HasTitle; - using mermaid::IsFile; - using mermaid::IsFolder; - using mermaid::IsIncludeDependency; - - REQUIRE_THAT(src, HasTitle("Basic include diagram example")); - - REQUIRE_THAT(src, IsFolder(_A("lib1"))); - REQUIRE_THAT(src, IsFile(_A("lib1.h"))); - REQUIRE_THAT(src, IsFile(_A("t40001.cc"))); - REQUIRE_THAT(src, IsFile(_A("t40001_include1.h"))); - - REQUIRE_THAT(src, IsFile(_A("string"))); - REQUIRE_THAT(src, IsFile(_A("yaml-cpp/yaml.h"))); - - REQUIRE_THAT( - src, IsAssociation(_A("t40001.cc"), _A("t40001_include1.h"))); - REQUIRE_THAT(src, IsAssociation(_A("t40001_include1.h"), _A("lib1.h"))); - - REQUIRE_THAT( - src, IsIncludeDependency(_A("t40001_include1.h"), _A("string"))); - - REQUIRE_THAT(src, HasComment("t40001 test diagram of type include")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsSystemHeaderDependency( + src, "include/t40001_include1.h", "string")); + }); } diff --git a/tests/t40002/test_case.h b/tests/t40002/test_case.h index bf09cb1d..456d9d2e 100644 --- a/tests/t40002/test_case.h +++ b/tests/t40002/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t40002/test_case.cc + * tests/t40002/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,153 +16,60 @@ * limitations under the License. */ -TEST_CASE("t40002", "[test-case][include]") +TEST_CASE("t40002") { - auto [config, db] = load_config("t40002"); + using namespace clanguml::test; - auto diagram = config.diagrams["t40002_include"]; + auto [config, db, diagram, model] = + CHECK_INCLUDE_MODEL("t40002", "t40002_include"); - REQUIRE(diagram->name == "t40002_include"); + CHECK_INCLUDE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsFolder(src, "include")); + REQUIRE(IsFolder(src, "include/lib1")); + REQUIRE(IsFolder(src, "include/lib2")); + REQUIRE(IsFolder(src, "src")); + REQUIRE(IsFolder(src, "src/lib1")); + REQUIRE(IsFolder(src, "src/lib2")); + REQUIRE(IsFile(src, "include/lib1/lib1.h")); + REQUIRE(IsFile(src, "include/lib2/lib2.h")); + REQUIRE(!IsFile(src, "include/lib2/lib2_detail.h")); + REQUIRE(IsFile(src, "src/lib1/lib1.cc")); + REQUIRE(IsFile(src, "src/lib2/lib2.cc")); + REQUIRE(IsFile(src, "src/t40002.cc")); - auto model = generate_include_diagram(*db, diagram); + REQUIRE(!IsFile(src, "string")); - REQUIRE(model->name() == "t40002_include"); + REQUIRE( + IsHeaderDependency(src, "src/t40002.cc", "include/lib1/lib1.h")); + REQUIRE(IsHeaderDependency( + src, "include/lib1/lib1.h", "include/lib2/lib2.h")); + REQUIRE( + IsHeaderDependency(src, "src/lib1/lib1.cc", "include/lib1/lib1.h")); + REQUIRE( + IsHeaderDependency(src, "src/lib2/lib2.cc", "include/lib2/lib2.h")); - { - auto src = generate_include_puml(diagram, *model); + REQUIRE(HasLink(src, "t40002.cc", + fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" + "t40002/src/t40002.cc#L0", + clanguml::util::get_git_commit()), + "t40002.cc")); - AliasMatcher _A(src); + REQUIRE(HasLink(src, "lib1.cc", + fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" + "t40002/src/lib1/lib1.cc#L0", + clanguml::util::get_git_commit()), + "lib1.cc")); - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); + REQUIRE(HasLink(src, "lib1.h", + fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" + "t40002/include/lib1/lib1.h#L0", + clanguml::util::get_git_commit()), + "lib1.h")); - REQUIRE_THAT(src, IsFolder("lib1")); - REQUIRE_THAT(src, IsFolder("lib2")); - REQUIRE_THAT(src, IsFile("lib1.h")); - REQUIRE_THAT(src, IsFile("lib2.h")); - REQUIRE_THAT(src, !IsFile("lib2_detail.h")); - REQUIRE_THAT(src, IsFile("t40002.cc")); - REQUIRE_THAT(src, IsFile("lib1.cc")); - REQUIRE_THAT(src, IsFile("lib2.cc")); - - REQUIRE_THAT(src, !IsFile("string")); - - REQUIRE_THAT(src, IsAssociation(_A("t40002.cc"), _A("lib1.h"))); - REQUIRE_THAT(src, IsAssociation(_A("lib1.h"), _A("lib2.h"))); - REQUIRE_THAT(src, IsAssociation(_A("lib1.cc"), _A("lib1.h"))); - REQUIRE_THAT(src, IsAssociation(_A("lib2.cc"), _A("lib2.h"))); - - REQUIRE_THAT(src, - HasLink(_A("t40002.cc"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t40002/src/t40002.cc#L0", - clanguml::util::get_git_commit()), - "t40002.cc")); - - REQUIRE_THAT(src, - HasLink(_A("lib1.cc"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t40002/src/lib1/lib1.cc#L0", - clanguml::util::get_git_commit()), - "lib1.cc")); - - REQUIRE_THAT(src, - HasLink(_A("lib1.h"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t40002/include/lib1/lib1.h#L0", - clanguml::util::get_git_commit()), - "lib1.h")); - - REQUIRE_THAT(src, - HasLink(_A("lib2.h"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t40002/include/lib2/lib2.h#L0", - clanguml::util::get_git_commit()), - "lib2.h")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_include_json(diagram, *model); - - using namespace json; - - REQUIRE(IsFolder(j, "include")); - REQUIRE(IsFolder(j, "include/lib1")); - REQUIRE(IsFolder(j, "include/lib2")); - REQUIRE(IsFolder(j, "src")); - REQUIRE(IsFolder(j, "src/lib1")); - REQUIRE(IsFolder(j, "src/lib2")); - REQUIRE(IsFile(j, "include/lib1/lib1.h")); - REQUIRE(IsFile(j, "include/lib2/lib2.h")); - REQUIRE(!IsFile(j, "include/lib2/lib2_detail.h")); - REQUIRE(IsFile(j, "src/lib1/lib1.cc")); - REQUIRE(IsFile(j, "src/lib2/lib2.cc")); - REQUIRE(IsFile(j, "src/t40002.cc")); - - REQUIRE(!IsFile(j, "string")); - - REQUIRE(IsAssociation(j, "src/t40002.cc", "include/lib1/lib1.h")); - REQUIRE(IsAssociation(j, "include/lib1/lib1.h", "include/lib2/lib2.h")); - REQUIRE(IsAssociation(j, "src/lib1/lib1.cc", "include/lib1/lib1.h")); - REQUIRE(IsAssociation(j, "src/lib2/lib2.cc", "include/lib2/lib2.h")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_include_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::HasLink; - using mermaid::IsFile; - using mermaid::IsFolder; - - REQUIRE_THAT(src, IsFolder(_A("lib1"))); - REQUIRE_THAT(src, IsFolder(_A("lib2"))); - REQUIRE_THAT(src, IsFile(_A("lib1.h"))); - REQUIRE_THAT(src, IsFile(_A("lib2.h"))); - REQUIRE_THAT(src, !IsFile(_A("lib2_detail.h"))); - REQUIRE_THAT(src, IsFile(_A("t40002.cc"))); - REQUIRE_THAT(src, IsFile(_A("lib1.cc"))); - REQUIRE_THAT(src, IsFile(_A("lib2.cc"))); - - REQUIRE_THAT(src, !IsFile(_A("string"))); - - REQUIRE_THAT(src, IsAssociation(_A("t40002.cc"), _A("lib1.h"))); - REQUIRE_THAT(src, IsAssociation(_A("lib1.h"), _A("lib2.h"))); - REQUIRE_THAT(src, IsAssociation(_A("lib1.cc"), _A("lib1.h"))); - REQUIRE_THAT(src, IsAssociation(_A("lib2.cc"), _A("lib2.h"))); - - REQUIRE_THAT(src, - HasLink(_A("t40002.cc"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t40002/src/t40002.cc#L0", - clanguml::util::get_git_commit()), - "t40002.cc")); - - REQUIRE_THAT(src, - HasLink(_A("lib1.cc"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t40002/src/lib1/lib1.cc#L0", - clanguml::util::get_git_commit()), - "lib1.cc")); - - REQUIRE_THAT(src, - HasLink(_A("lib1.h"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t40002/include/lib1/lib1.h#L0", - clanguml::util::get_git_commit()), - "lib1.h")); - - REQUIRE_THAT(src, - HasLink(_A("lib2.h"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t40002/include/lib2/lib2.h#L0", - clanguml::util::get_git_commit()), - "lib2.h")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(HasLink(src, "lib2.h", + fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" + "t40002/include/lib2/lib2.h#L0", + clanguml::util::get_git_commit()), + "lib2.h")); + }); } diff --git a/tests/t40003/test_case.h b/tests/t40003/test_case.h index 5b44ae41..119c43d3 100644 --- a/tests/t40003/test_case.h +++ b/tests/t40003/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t40003/test_case.cc + * tests/t40003/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,84 +16,29 @@ * limitations under the License. */ -TEST_CASE("t40003", "[test-case][include]") +TEST_CASE("t40003") { - auto [config, db] = load_config("t40003"); + using namespace clanguml::test; - auto diagram = config.diagrams["t40003_include"]; + auto [config, db, diagram, model] = + CHECK_INCLUDE_MODEL("t40003", "t40003_include"); - REQUIRE(diagram->name == "t40003_include"); + CHECK_INCLUDE_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsFolder(src, "include/dependants")); + REQUIRE(IsFolder(src, "include/dependencies")); + REQUIRE(IsFolder(src, "src/dependants")); + REQUIRE(IsFolder(src, "src/dependencies")); - auto model = generate_include_diagram(*db, diagram); + REQUIRE(IsFile(src, "include/dependants/t1.h")); + REQUIRE(IsFile(src, "include/dependants/t2.h")); + REQUIRE(IsFile(src, "include/dependants/t3.h")); + REQUIRE(!IsFile(src, "include/dependants/t4.h")); + REQUIRE(IsFile(src, "src/dependants/t1.cc")); - REQUIRE(model->name() == "t40003_include"); - - { - auto src = generate_include_puml(diagram, *model); - - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - REQUIRE_THAT(src, IsFolder("dependants")); - REQUIRE_THAT(src, IsFolder("dependencies")); - - REQUIRE_THAT(src, IsFile("t1.h")); - REQUIRE_THAT(src, IsFile("t2.h")); - REQUIRE_THAT(src, IsFile("t3.h")); - - REQUIRE_THAT(src, !IsFile("t4.h")); - REQUIRE_THAT(src, IsFile("t5.h")); - REQUIRE_THAT(src, !IsFile("t6.h")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_include_json(diagram, *model); - - using namespace json; - - REQUIRE(IsFolder(j, "include/dependants")); - REQUIRE(IsFolder(j, "include/dependencies")); - REQUIRE(IsFolder(j, "src/dependants")); - REQUIRE(IsFolder(j, "src/dependencies")); - - REQUIRE(IsFile(j, "include/dependants/t1.h")); - REQUIRE(IsFile(j, "include/dependants/t2.h")); - REQUIRE(IsFile(j, "include/dependants/t3.h")); - REQUIRE(!IsFile(j, "include/dependants/t4.h")); - REQUIRE(IsFile(j, "src/dependants/t1.cc")); - - REQUIRE(IsFile(j, "include/dependencies/t1.h")); - REQUIRE(IsFile(j, "include/dependencies/t2.h")); - REQUIRE(IsFile(j, "include/dependencies/t3.h")); - REQUIRE(!IsFile(j, "include/dependencies/t4.h")); - REQUIRE(IsFile(j, "src/dependencies/t2.cc")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_include_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::HasLink; - using mermaid::IsFile; - using mermaid::IsFolder; - - REQUIRE_THAT(src, IsFolder(_A("dependants"))); - REQUIRE_THAT(src, IsFolder(_A("dependencies"))); - - REQUIRE_THAT(src, IsFile(_A("t1.h"))); - REQUIRE_THAT(src, IsFile(_A("t2.h"))); - REQUIRE_THAT(src, IsFile(_A("t3.h"))); - - REQUIRE_THAT(src, !IsFile(_A("t4.h"))); - REQUIRE_THAT(src, IsFile(_A("t5.h"))); - REQUIRE_THAT(src, !IsFile(_A("t6.h"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsFile(src, "include/dependencies/t1.h")); + REQUIRE(IsFile(src, "include/dependencies/t2.h")); + REQUIRE(IsFile(src, "include/dependencies/t3.h")); + REQUIRE(!IsFile(src, "include/dependencies/t4.h")); + REQUIRE(IsFile(src, "src/dependencies/t2.cc")); + }); } diff --git a/tests/t90000/test_case.h b/tests/t90000/test_case.h index a517f474..945733c5 100644 --- a/tests/t90000/test_case.h +++ b/tests/t90000/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t90000/test_case.cc + * tests/t90000/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,40 +16,21 @@ * limitations under the License. */ -TEST_CASE("t90000", "[test-case][config]") +TEST_CASE("t90000") { - auto [config, db] = load_config("t90000"); + using namespace clanguml::test; - auto diagram = config.diagrams["t90000_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t90000", "t90000_class"); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t90000_class"); - - { - auto puml = generate_class_puml(diagram, *model); - AliasMatcher _A(puml); - - REQUIRE_THAT(puml, StartsWith("@startuml")); - REQUIRE_THAT(puml, EndsWith("@enduml\n")); - - REQUIRE_THAT(puml, IsClass(_A("Foo"))); - REQUIRE_THAT(puml, IsClass(_A("Boo"))); - - save_puml(config.output_directory(), diagram->name + ".puml", puml); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto mmd = generate_class_mermaid(diagram, *model); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd); - } + CHECK_CLASS_DIAGRAM( + config, diagram, *model, + [](const plantuml_t &src) { + REQUIRE(IsClass(src, "Foo")); + REQUIRE(IsClass(src, "Boo")); + }, + [](const mermaid_t &src) { + REQUIRE(IsClass(src, "Foo")); + REQUIRE(IsClass(src, "Boo")); + }); } diff --git a/tests/t90001/test_case.h b/tests/t90001/test_case.h index 812f5a0d..99767514 100644 --- a/tests/t90001/test_case.h +++ b/tests/t90001/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t90001/test_case.cc + * tests/t90001/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,8 +16,9 @@ * limitations under the License. */ -TEST_CASE("t90001", "[test-case][config]") +TEST_CASE("t90001") { + using namespace clanguml::test; using clanguml::error::empty_diagram_error; auto [config, db] = load_config("t90001"); @@ -31,12 +32,12 @@ TEST_CASE("t90001", "[test-case][config]") REQUIRE(model->name() == "t90001_class"); + REQUIRE_THROWS_AS(render_class_diagram(diagram, *model), + empty_diagram_error); + REQUIRE_THROWS_AS(render_class_diagram(diagram, *model), + empty_diagram_error); REQUIRE_THROWS_AS( - generate_class_puml(diagram, *model), empty_diagram_error); - REQUIRE_THROWS_AS( - generate_class_json(diagram, *model), empty_diagram_error); - REQUIRE_THROWS_AS( - generate_class_mermaid(diagram, *model), empty_diagram_error); + render_class_diagram(diagram, *model), empty_diagram_error); } { @@ -48,12 +49,12 @@ TEST_CASE("t90001", "[test-case][config]") REQUIRE(model->name() == "t90001_sequence"); - REQUIRE_THROWS_AS( - generate_sequence_puml(diagram, *model), empty_diagram_error); - REQUIRE_THROWS_AS( - generate_sequence_json(diagram, *model), empty_diagram_error); - REQUIRE_THROWS_AS( - generate_sequence_mermaid(diagram, *model), empty_diagram_error); + REQUIRE_THROWS_AS(render_sequence_diagram(diagram, *model), + empty_diagram_error); + REQUIRE_THROWS_AS(render_sequence_diagram(diagram, *model), + empty_diagram_error); + REQUIRE_THROWS_AS(render_sequence_diagram(diagram, *model), + empty_diagram_error); } { @@ -65,12 +66,12 @@ TEST_CASE("t90001", "[test-case][config]") REQUIRE(model->name() == "t90001_package"); - REQUIRE_THROWS_AS( - generate_package_puml(diagram, *model), empty_diagram_error); - REQUIRE_THROWS_AS( - generate_package_json(diagram, *model), empty_diagram_error); - REQUIRE_THROWS_AS( - generate_package_mermaid(diagram, *model), empty_diagram_error); + REQUIRE_THROWS_AS(render_package_diagram(diagram, *model), + empty_diagram_error); + REQUIRE_THROWS_AS(render_package_diagram(diagram, *model), + empty_diagram_error); + REQUIRE_THROWS_AS(render_package_diagram(diagram, *model), + empty_diagram_error); } { @@ -82,11 +83,11 @@ TEST_CASE("t90001", "[test-case][config]") REQUIRE(model->name() == "t90001_include"); - REQUIRE_THROWS_AS( - generate_include_puml(diagram, *model), empty_diagram_error); - REQUIRE_THROWS_AS( - generate_include_json(diagram, *model), empty_diagram_error); - REQUIRE_THROWS_AS( - generate_include_mermaid(diagram, *model), empty_diagram_error); + REQUIRE_THROWS_AS(render_include_diagram(diagram, *model), + empty_diagram_error); + REQUIRE_THROWS_AS(render_include_diagram(diagram, *model), + empty_diagram_error); + REQUIRE_THROWS_AS(render_include_diagram(diagram, *model), + empty_diagram_error); } } diff --git a/tests/test_cases.cc b/tests/test_cases.cc index 524f994e..1b4b8d3c 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -100,60 +100,33 @@ auto generate_diagram_impl(clanguml::common::compilation_database &db, return model; } -template -auto generate_diagram_puml( +template +auto render_diagram( std::shared_ptr config, DiagramModel &model) { using diagram_config = DiagramConfig; using diagram_model = DiagramModel; using diagram_generator = typename clanguml::common::generators::diagram_generator_t< - DiagramConfig, - clanguml::common::generators::plantuml_generator_tag>::type; + DiagramConfig, typename GeneratorType::generator_tag>::type; std::stringstream ss; ss << diagram_generator(dynamic_cast(*config), model); - return ss.str(); + if constexpr (std::is_same_v) { + return nlohmann::json::parse(ss.str()); + } + else { + return ss.str(); + } } +} // namespace detail -template -auto generate_diagram_json( - std::shared_ptr config, DiagramModel &model) -{ - using diagram_config = DiagramConfig; - using diagram_model = DiagramModel; - using diagram_generator = - typename clanguml::common::generators::diagram_generator_t< - DiagramConfig, - clanguml::common::generators::json_generator_tag>::type; - - std::stringstream ss; - - ss << diagram_generator(dynamic_cast(*config), model); - - return nlohmann::json::parse(ss.str()); -} - -template -auto generate_diagram_mermaid( - std::shared_ptr config, DiagramModel &model) -{ - using diagram_config = DiagramConfig; - using diagram_model = DiagramModel; - using diagram_generator = - typename clanguml::common::generators::diagram_generator_t< - DiagramConfig, - clanguml::common::generators::mermaid_generator_tag>::type; - - std::stringstream ss; - - ss << diagram_generator(dynamic_cast(*config), model); - - return ss.str(); -} -} +/// +/// @defgroup Diagram generators +/// @{ +/// std::unique_ptr generate_class_diagram( clanguml::common::compilation_database &db, @@ -187,101 +160,7 @@ generate_include_diagram(clanguml::common::compilation_database &db, db, diagram); } -std::string generate_class_puml( - std::shared_ptr config, - clanguml::class_diagram::model::diagram &model) -{ - return detail::generate_diagram_puml( - config, model); -} - -std::string generate_sequence_puml( - std::shared_ptr config, - clanguml::sequence_diagram::model::diagram &model) -{ - return detail::generate_diagram_puml( - config, model); -} - -std::string generate_package_puml( - std::shared_ptr config, - clanguml::package_diagram::model::diagram &model) -{ - return detail::generate_diagram_puml( - config, model); -} - -std::string generate_include_puml( - std::shared_ptr config, - clanguml::include_diagram::model::diagram &model) -{ - return detail::generate_diagram_puml( - config, model); -} - -nlohmann::json generate_class_json( - std::shared_ptr config, - clanguml::class_diagram::model::diagram &model) -{ - return detail::generate_diagram_json( - config, model); -} - -nlohmann::json generate_sequence_json( - std::shared_ptr config, - clanguml::sequence_diagram::model::diagram &model) -{ - return detail::generate_diagram_json( - config, model); -} - -nlohmann::json generate_package_json( - std::shared_ptr config, - clanguml::package_diagram::model::diagram &model) -{ - return detail::generate_diagram_json( - config, model); -} - -nlohmann::json generate_include_json( - std::shared_ptr config, - clanguml::include_diagram::model::diagram &model) -{ - return detail::generate_diagram_json( - config, model); -} - -std::string generate_class_mermaid( - std::shared_ptr config, - clanguml::class_diagram::model::diagram &model) -{ - return detail::generate_diagram_mermaid( - config, model); -} - -std::string generate_sequence_mermaid( - std::shared_ptr config, - clanguml::sequence_diagram::model::diagram &model) -{ - return detail::generate_diagram_mermaid( - config, model); -} - -std::string generate_package_mermaid( - std::shared_ptr config, - clanguml::package_diagram::model::diagram &model) -{ - return detail::generate_diagram_mermaid( - config, model); -} - -std::string generate_include_mermaid( - std::shared_ptr config, - clanguml::include_diagram::model::diagram &model) -{ - return detail::generate_diagram_mermaid( - config, model); -} +/// }@ template void save_diagram(const std::filesystem::path &path, const T &diagram) @@ -326,7 +205,254 @@ void save_mermaid(const std::string &path, const std::string &filename, save_diagram(p, mmd); } -using namespace clanguml::test::matchers; +namespace clanguml::test { + +struct diagram_source_storage { + diagram_source_storage(plantuml_t &&p, json_t &&j, mermaid_t &&m) + : plantuml{std::move(p)} + , json{std::move(j)} + , mermaid{std::move(m)} + { + } + + template const T &get() const; + + plantuml_t plantuml; + json_t json; + mermaid_t mermaid; +}; + +template <> const plantuml_t &diagram_source_storage::get() const +{ + return plantuml; +} + +template <> const json_t &diagram_source_storage::get() const +{ + return json; +} + +template <> const mermaid_t &diagram_source_storage::get() const +{ + return mermaid; +} + +template +void try_run_test_case(const diagram_source_storage &diagrams, TC &&tc) +{ + if constexpr (std::is_invocable_v) { + try { + tc(diagrams.get()); + } + catch (doctest::TestFailureException &e) { + std::cout << "-----------------------------------------------------" + "--------------------------\n"; + std::cout << "Test case failed for diagram type " + << T::diagram_type_name << ": " + << "\n\n"; + std::cout << diagrams.get().to_string() << "\n"; + + throw e; + } + } +} + +template +DiagramType render_class_diagram(std::shared_ptr c, + clanguml::class_diagram::model::diagram &model) +{ + auto d = DiagramType{common::model::diagram_t::kClass, + detail::render_diagram( + c, model)}; + d.generate_packages = c->generate_packages(); + return d; +} + +template +DiagramType render_sequence_diagram( + std::shared_ptr c, + clanguml::sequence_diagram::model::diagram &model) +{ + return DiagramType{common::model::diagram_t::kSequence, + detail::render_diagram( + c, model)}; +} + +template +DiagramType render_package_diagram(std::shared_ptr c, + clanguml::package_diagram::model::diagram &model) +{ + return DiagramType{common::model::diagram_t::kPackage, + detail::render_diagram( + c, model)}; +} + +template +DiagramType render_include_diagram(std::shared_ptr c, + clanguml::include_diagram::model::diagram &model) +{ + return DiagramType{common::model::diagram_t::kInclude, + detail::render_diagram( + c, model)}; +} + +auto CHECK_CLASS_MODEL( + const std::string &test_name, const std::string &diagram_name) +{ + auto [config, db] = load_config(test_name); + + auto diagram = config.diagrams[diagram_name]; + + REQUIRE(diagram->name == diagram_name); + + auto model = generate_class_diagram(*db, diagram); + + REQUIRE(model->name() == diagram_name); + + return std::make_tuple( + std::move(config), std::move(db), std::move(diagram), std::move(model)); +} + +auto CHECK_SEQUENCE_MODEL( + const std::string &test_name, const std::string &diagram_name) +{ + auto [config, db] = load_config(test_name); + + auto diagram = config.diagrams[diagram_name]; + + REQUIRE(diagram->name == diagram_name); + + auto model = generate_sequence_diagram(*db, diagram); + + REQUIRE(model->name() == diagram_name); + + return std::make_tuple( + std::move(config), std::move(db), std::move(diagram), std::move(model)); +} + +auto CHECK_PACKAGE_MODEL( + const std::string &test_name, const std::string &diagram_name) +{ + auto [config, db] = load_config(test_name); + + auto diagram = config.diagrams[diagram_name]; + + REQUIRE(diagram->name == diagram_name); + + auto model = generate_package_diagram(*db, diagram); + + REQUIRE(model->name() == diagram_name); + + return std::make_tuple( + std::move(config), std::move(db), std::move(diagram), std::move(model)); +} + +auto CHECK_INCLUDE_MODEL( + const std::string &test_name, const std::string &diagram_name) +{ + auto [config, db] = load_config(test_name); + + auto diagram = config.diagrams[diagram_name]; + + REQUIRE(diagram->name == diagram_name); + + auto model = generate_include_diagram(*db, diagram); + + REQUIRE(model->name() == diagram_name); + + return std::make_tuple( + std::move(config), std::move(db), std::move(diagram), std::move(model)); +} + +template +void CHECK_DIAGRAM_IMPL( + const diagram_source_storage &diagrams, TC &&tc, TCs &&...tcs) +{ + try_run_test_case(diagrams, tc); + try_run_test_case(diagrams, tc); + try_run_test_case(diagrams, tc); + + if constexpr (sizeof...(tcs) > 0) { + CHECK_DIAGRAM_IMPL(diagrams, std::forward(tcs)...); + } +} + +template +void CHECK_CLASS_DIAGRAM(const clanguml::config::config &config, + DiagramConfig diagram, DiagramModel &model, TCs &&...tcs) +{ + diagram_source_storage diagram_sources{ + render_class_diagram(diagram, model), + render_class_diagram(diagram, model), + render_class_diagram(diagram, model)}; + + CHECK_DIAGRAM_IMPL(diagram_sources, std::forward(tcs)...); + + save_puml(config.output_directory(), diagram->name + ".puml", + diagram_sources.plantuml.src); + save_json(config.output_directory(), diagram->name + ".json", + diagram_sources.json.src); + save_mermaid(config.output_directory(), diagram->name + ".mmd", + diagram_sources.mermaid.src); +} + +template +void CHECK_SEQUENCE_DIAGRAM(const clanguml::config::config &config, + DiagramConfig diagram, DiagramModel &model, TCs &&...tcs) +{ + diagram_source_storage diagram_sources{ + render_sequence_diagram(diagram, model), + render_sequence_diagram(diagram, model), + render_sequence_diagram(diagram, model)}; + + CHECK_DIAGRAM_IMPL(diagram_sources, std::forward(tcs)...); + + save_puml(config.output_directory(), diagram->name + ".puml", + diagram_sources.plantuml.src); + save_json(config.output_directory(), diagram->name + ".json", + diagram_sources.json.src); + save_mermaid(config.output_directory(), diagram->name + ".mmd", + diagram_sources.mermaid.src); +} + +template +void CHECK_PACKAGE_DIAGRAM(const clanguml::config::config &config, + DiagramConfig diagram, DiagramModel &model, TCs &&...tcs) +{ + diagram_source_storage diagram_sources{ + render_package_diagram(diagram, model), + render_package_diagram(diagram, model), + render_package_diagram(diagram, model)}; + + CHECK_DIAGRAM_IMPL(diagram_sources, std::forward(tcs)...); + + save_puml(config.output_directory(), diagram->name + ".puml", + diagram_sources.plantuml.src); + save_json(config.output_directory(), diagram->name + ".json", + diagram_sources.json.src); + save_mermaid(config.output_directory(), diagram->name + ".mmd", + diagram_sources.mermaid.src); +} + +template +void CHECK_INCLUDE_DIAGRAM(const clanguml::config::config &config, + DiagramConfig diagram, DiagramModel &model, TCs &&...tcs) +{ + diagram_source_storage diagram_sources{ + render_include_diagram(diagram, model), + render_include_diagram(diagram, model), + render_include_diagram(diagram, model)}; + + CHECK_DIAGRAM_IMPL(diagram_sources, std::forward(tcs)...); + + save_puml(config.output_directory(), diagram->name + ".puml", + diagram_sources.plantuml.src); + save_json(config.output_directory(), diagram->name + ".json", + diagram_sources.json.src); + save_mermaid(config.output_directory(), diagram->name + ".mmd", + diagram_sources.mermaid.src); +} +} // namespace clanguml::test /// /// Class diagram tests @@ -475,11 +601,13 @@ using namespace clanguml::test::matchers; #include "t20046/test_case.h" #include "t20047/test_case.h" #include "t20048/test_case.h" + #if defined(ENABLE_CUDA_TEST_CASES) #include "t20049/test_case.h" #include "t20050/test_case.h" #include "t20051/test_case.h" #endif + #include "t20052/test_case.h" #include "t20053/test_case.h" @@ -506,6 +634,7 @@ using namespace clanguml::test::matchers; /// /// Include diagram tests /// + #include "t40001/test_case.h" #include "t40002/test_case.h" #include "t40003/test_case.h" @@ -521,30 +650,23 @@ using namespace clanguml::test::matchers; /// int main(int argc, char *argv[]) { - Catch::Session session; - using namespace Catch::clara; + doctest::Context context; - bool debug_log{false}; - auto cli = session.cli() | - Opt(debug_log, "debug_log")["-u"]["--debug-log"]("Enable debug logs"); - - session.cli(cli); - - int returnCode = session.applyCommandLine(argc, argv); - if (returnCode != 0) - return returnCode; + context.applyCommandLine(argc, argv); clanguml::cli::cli_handler clih; std::vector argvv = { "clang-uml", "--config", "./test_config_data/simple.yml"}; - if (debug_log) - argvv.push_back("-vvv"); - else - argvv.push_back("-q"); + argvv.push_back("-q"); clih.handle_options(argvv.size(), argvv.data()); - return session.run(); + int res = context.run(); + + if (context.shouldExit()) + return res; + + return res; } diff --git a/tests/test_cases.h b/tests/test_cases.h index b8e61102..3ab946b3 100644 --- a/tests/test_cases.h +++ b/tests/test_cases.h @@ -25,6 +25,7 @@ #include "class_diagram/visitor/translation_unit_visitor.h" #include "common/clang_utils.h" #include "common/compilation_database.h" +#include "common/generators/generators.h" #include "config/config.h" #include "include_diagram/generators/plantuml/include_diagram_generator.h" #include "include_diagram/visitor/translation_unit_visitor.h" @@ -34,10 +35,8 @@ #include "sequence_diagram/visitor/translation_unit_visitor.h" #include "util/util.h" -#define CATCH_CONFIG_RUNNER -#define CATCH_CONFIG_CONSOLE_WIDTH 512 - -#include "catch.h" +#define DOCTEST_CONFIG_IMPLEMENT +#include "doctest/doctest.h" #include #include @@ -47,45 +46,12 @@ #include #include -using Catch::Matchers::Contains; -using Catch::Matchers::EndsWith; -using Catch::Matchers::Equals; -using Catch::Matchers::Matches; -using Catch::Matchers::StartsWith; -using Catch::Matchers::VectorContains; - using namespace clanguml::util; std::pair load_config(const std::string &test_name); -std::string generate_sequence_puml( - std::shared_ptr config, - clanguml::sequence_diagram::model::diagram &model); - -std::string generate_class_puml( - std::shared_ptr config, - clanguml::class_diagram::model::diagram &model); - -void save_puml(const std::string &path, const std::string &puml); - -namespace clanguml { -namespace test { -namespace matchers { - -using Catch::CaseSensitive; -using Catch::Matchers::StdString::CasedString; -using Catch::Matchers::StdString::ContainsMatcher; -using Catch::Matchers::StdString::RegexMatcher; - -struct JsonMatcherBase : Catch::MatcherBase { - JsonMatcherBase( - std::string const &operation, CasedString const &comparator); - std::string describe() const override; - - CasedString m_comparator; - std::string m_operation; -}; +namespace clanguml::test { template constexpr bool has_type() noexcept { @@ -116,236 +82,71 @@ struct Default { }; struct Deleted { }; -struct HasCallWithResultMatcher : ContainsMatcher { - HasCallWithResultMatcher( - CasedString const &comparator, CasedString const &resultComparator) - : ContainsMatcher(comparator) - , m_resultComparator{resultComparator} +struct Entrypoint { }; + +struct Exitpoint { }; + +struct CUDAKernel { }; +struct CUDADevice { }; + +struct InControlCondition { }; +struct Response { }; +struct NamespacePackage { }; +struct ModulePackage { }; +struct DirectoryPackage { }; + +template std::string package_type_name(); + +template <> std::string package_type_name() +{ + return "namespace"; +} + +template <> std::string package_type_name() { return "module"; } + +template <> std::string package_type_name() +{ + return "directory"; +} + +template struct diagram_source_t { + diagram_source_t(clanguml::common::model::diagram_t dt, T &&s) { + diagram_type = dt; + src = std::move(s); } - bool match(std::string const &source) const override + bool contains(std::string name) const; + + virtual std::string get_alias(std::string name) const { - return Catch::contains( - m_comparator.adjustString(source), m_comparator.m_str) && - Catch::contains( - m_comparator.adjustString(source), m_resultComparator.m_str); + return "__INVALID_ALIAS__"; } - CasedString m_resultComparator; + virtual std::string get_alias(std::string ns, std::string name) const + { + return get_alias(fmt::format("{}::{}", ns, name)); + } + + bool search(const std::string &pattern) const; + + int64_t find(const std::string &pattern, int64_t offset = 0) const; + + std::string to_string() const; + + T src; + clanguml::common::model::diagram_t diagram_type; + bool generate_packages{false}; }; -template class HasCallMatcher : public Catch::MatcherBase { - T m_from, m_to, m_message; - bool m_is_response; - std::string m_call_arrow, m_return_arrow; - std::string call_pattern, response_pattern; +struct plantuml_t : public diagram_source_t { + using diagram_source_t::diagram_source_t; + using source_type = std::string; + using generator_tag = clanguml::common::generators::plantuml_generator_tag; -public: - HasCallMatcher(T from, T to, T message, bool is_response = false, - const std::string &call_arrow = "->", - const std::string &return_arrow = "-->") - : m_from(from) - , m_to{to} - , m_message{message} - , m_is_response{is_response} - , m_call_arrow{call_arrow} - , m_return_arrow{return_arrow} - { - util::replace_all(m_message, "(", "\\("); - util::replace_all(m_message, ")", "\\)"); - util::replace_all(m_message, "*", "\\*"); - util::replace_all(m_message, "[", "\\["); - util::replace_all(m_message, "]", "\\]"); - util::replace_all(m_message, "+", "\\+"); + inline static const std::string diagram_type_name{"PlantUML"}; - call_pattern = fmt::format("{} {} {} " - "(\\[\\[.*\\]\\] )?: {}", - m_from, m_call_arrow, m_to, m_message); - - response_pattern = fmt::format( - "{} {} {} : //{}//", m_from, m_return_arrow, m_to, m_message); - } - - bool match(T const &in) const override - { - std::regex r{m_is_response ? response_pattern : call_pattern}; - std::smatch base_match; - std::regex_search(in, base_match, r); - if (base_match.size() > 0) - return true; - - return false; - } - - std::string describe() const override - { - std::ostringstream ss; - ss << "has call " - << fmt::format( - "{} {} {} : {}", m_from, m_call_arrow, m_to, m_message); - return ss.str(); - } -}; - -auto HasCall(std::string const &from, std::string const &to, - std::string const &message, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return HasCallMatcher(from, to, message, false); -} - -auto HasResponse(std::string const &from, std::string const &to, - std::string const &message, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return HasCallMatcher(to, from, message, true); -} - -auto HasCallInControlCondition(std::string const &from, std::string const &to, - std::string const &message, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return HasCallMatcher(from, to, fmt::format("**[**{}**]**", message)); -} - -auto HasCall(std::string const &from, std::string const &message, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return HasCall(from, from, message, caseSensitivity); -} - -namespace mermaid { -template class HasCallMatcher : public Catch::MatcherBase { - T m_from, m_to, m_message; - bool m_is_response; - std::string m_call_arrow, m_return_arrow; - std::string call_pattern, response_pattern; - -public: - HasCallMatcher(T from, T to, T message, bool is_response = false, - const std::string &call_arrow = "->>", - const std::string &return_arrow = "-->>") - : m_from(from) - , m_to{to} - , m_message{message} - , m_is_response{is_response} - , m_call_arrow{call_arrow} - , m_return_arrow{return_arrow} - { - util::replace_all(m_message, "(", "\\("); - util::replace_all(m_message, ")", "\\)"); - util::replace_all(m_message, "*", "\\*"); - util::replace_all(m_message, "[", "\\["); - util::replace_all(m_message, "]", "\\]"); - util::replace_all(m_message, "+", "\\+"); - - call_pattern = - fmt::format("{} {} {} : {}", m_from, m_call_arrow, m_to, m_message); - - response_pattern = fmt::format( - "{} {} {} : {}", m_from, m_return_arrow, m_to, m_message); - } - - bool match(T const &in) const override - { - std::regex r{m_is_response ? response_pattern : call_pattern}; - std::smatch base_match; - std::regex_search(in, base_match, r); - if (base_match.size() > 0) - return true; - - return false; - } - - std::string describe() const override - { - std::ostringstream ss; - ss << "has call " - << fmt::format( - "{} {} {} : {}", m_from, m_call_arrow, m_to, m_message); - return ss.str(); - } -}; - -auto HasCall(std::string const &from, std::string const &to, - std::string const &message, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return mermaid::HasCallMatcher(from, to, message, false); -} - -auto HasCallInControlCondition(std::string const &from, std::string const &to, - std::string const &message, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return mermaid::HasCallMatcher(from, to, fmt::format("[{}]", message)); -} - -auto HasResponse(std::string const &from, std::string const &to, - std::string const &message, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return HasCallMatcher(to, from, message, true, "->>", "-->>"); -} - -auto HasCall(std::string const &from, std::string const &message, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return mermaid::HasCall(from, from, message, caseSensitivity); -} -} - -ContainsMatcher HasEntrypoint(std::string const &to, std::string const &message, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher( - CasedString(fmt::format("[-> {} : {}", to, message), caseSensitivity)); -} - -namespace mermaid { -ContainsMatcher HasEntrypoint(std::string const &to, std::string const &message, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher(CasedString( - fmt::format("* ->> {} : {}", to, message), caseSensitivity)); -} -} - -ContainsMatcher HasExitpoint(std::string const &to, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher( - CasedString(fmt::format("[<-- {}", to), caseSensitivity)); -} - -namespace mermaid { -ContainsMatcher HasExitpoint(std::string const &to, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher( - CasedString(fmt::format("{} -->> *", to), caseSensitivity)); -} -} - -std::string _NS(std::string_view s) -{ - return fmt::format( - "clanguml::{}::{}", Catch::getResultCapture().getCurrentTestName(), s); -} - -class NamespaceWrapper { - -private: -}; - -struct AliasMatcher { - AliasMatcher(const std::string &puml_) - : puml{split(puml_, "\n")} - { - } - - std::string operator()(std::string name) + std::string get_alias(std::string name) const override { std::vector patterns; @@ -377,31 +178,27 @@ struct AliasMatcher { std::smatch base_match; - for (const auto &line : puml) { - for (const auto &pattern : patterns) { - if (std::regex_search(line, base_match, pattern) && - base_match.size() == 2) { - std::ssub_match base_sub_match = base_match[1]; - std::string alias = base_sub_match.str(); - return trim(alias); - } + for (const auto &pattern : patterns) { + if (std::regex_search(src, base_match, pattern) && + base_match.size() == 2) { + std::ssub_match base_sub_match = base_match[1]; + std::string alias = base_sub_match.str(); + return trim(alias); } } return fmt::format("__INVALID__ALIAS__({})", name); } - - const std::vector puml; }; -namespace mermaid { -struct AliasMatcher { - AliasMatcher(const std::string &mmd_) - : mmd{split(mmd_, "\n")} - { - } +struct mermaid_t : public diagram_source_t { + using diagram_source_t::diagram_source_t; + using source_type = std::string; + using generator_tag = clanguml::common::generators::mermaid_generator_tag; - std::string operator()(std::string name) + inline static const std::string diagram_type_name{"MermaidJS"}; + + std::string get_alias_impl(std::string name) const { std::vector patterns; @@ -425,30 +222,19 @@ struct AliasMatcher { std::smatch base_match; - for (const auto &line : mmd) { - for (const auto &pattern : patterns) { - if (std::regex_search(line, base_match, pattern) && - base_match.size() == 2) { - std::ssub_match base_sub_match = base_match[1]; - std::string alias = base_sub_match.str(); - return trim(alias); - } + for (const auto &pattern : patterns) { + if (std::regex_search(src, base_match, pattern) && + base_match.size() == 2) { + std::ssub_match base_sub_match = base_match[1]; + std::string alias = base_sub_match.str(); + return trim(alias); } } - return "__INVALID__ALIAS__"; + return fmt::format("__INVALID__ALIAS__({})", name); } - const std::vector mmd; -}; - -struct SequenceDiagramAliasMatcher { - SequenceDiagramAliasMatcher(const std::string &mmd_) - : mmd{split(mmd_, "\n")} - { - } - - std::string operator()(std::string name) + std::string get_alias_sequence_diagram_impl(std::string name) const { std::vector patterns; @@ -461,436 +247,592 @@ struct SequenceDiagramAliasMatcher { util::replace_all(name, "[", "\\["); util::replace_all(name, "]", "\\]"); - patterns.push_back( - std::regex{"participant\\s" + alias_regex + "\\sas\\s" + name}); + patterns.push_back(std::regex{ + "participant\\s" + alias_regex + "\\sas\\s" + name + "\\n"}); + patterns.push_back(std::regex{"participant\\s" + alias_regex + + "\\sas\\s<< CUDA Kernel >>
" + name + "\\n"}); + patterns.push_back(std::regex{"participant\\s" + alias_regex + + "\\sas\\s<< CUDA Device >>
" + name + "\\n"}); std::smatch base_match; - for (const auto &line : mmd) { - for (const auto &pattern : patterns) { - if (std::regex_search(line, base_match, pattern) && - base_match.size() == 2) { - std::ssub_match base_sub_match = base_match[1]; - std::string alias = base_sub_match.str(); - return trim(alias); - } + for (const auto &pattern : patterns) { + if (std::regex_search(src, base_match, pattern) && + base_match.size() == 2) { + std::ssub_match base_sub_match = base_match[1]; + std::string alias = base_sub_match.str(); + return trim(alias); } } - return "__INVALID__ALIAS__"; + return fmt::format("__INVALID__ALIAS__({})", name); } - const std::vector mmd; + std::string get_alias(std::string name) const override + { + if (diagram_type == common::model::diagram_t::kSequence) + return get_alias_sequence_diagram_impl(name); + + return get_alias_impl(name); + } }; -} -ContainsMatcher HasTitle(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +struct json_t : public diagram_source_t { + using diagram_source_t::diagram_source_t; + using source_type = nlohmann::json; + using generator_tag = clanguml::common::generators::json_generator_tag; + + inline static const std::string diagram_type_name{"JSON"}; +}; + +std::optional get_element_by_id( + const nlohmann::json &j, const std::string &id) { - return ContainsMatcher(CasedString("title " + str, caseSensitivity)); -} + if (!j.contains("elements")) + return {}; -namespace mermaid { -ContainsMatcher HasTitle(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher(CasedString("title: " + str, caseSensitivity)); -} -} + for (const nlohmann::json &e : j["elements"]) { + if (e["id"] == id) + return {e}; -ContainsMatcher IsClass(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher(CasedString("class " + str, caseSensitivity)); -} - -namespace mermaid { -auto IsClass(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher(CasedString("class " + str, caseSensitivity)); -} -} - -ContainsMatcher IsUnion(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher( - CasedString("class " + str + " <>", caseSensitivity)); -} - -namespace mermaid { -auto IsUnion(std::string const &alias, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return Catch::Matchers::Matches( - std::string("class ") + alias + " \\{\\n\\s+<>", - caseSensitivity); -} -} - -ContainsMatcher IsClassTemplate(std::string const &str, - std::string const &tmplt, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher(CasedString( - fmt::format("class \"{}<{}>\"", str, tmplt), caseSensitivity)); -} - -ContainsMatcher IsConcept(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher( - CasedString("class " + str + " <>", caseSensitivity)); -} - -namespace mermaid { -auto IsConcept(std::string const &alias, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return Catch::Matchers::Matches( - std::string("class ") + alias + " \\{\\n\\s+<>", - caseSensitivity); -} -} - -ContainsMatcher IsEnum(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher(CasedString("enum " + str, caseSensitivity)); -} - -namespace mermaid { -auto IsEnum(std::string const &alias, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return Catch::Matchers::Matches( - std::string("class ") + alias + " \\{\\n\\s+<>", - caseSensitivity); -} -} - -ContainsMatcher IsAbstractClass(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher(CasedString("abstract " + str, caseSensitivity)); -} - -namespace mermaid { -auto IsAbstractClass(std::string const &alias, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return Catch::Matchers::Matches( - std::string("class ") + alias + " \\{\\n\\s+<>", - caseSensitivity); -} -} - -ContainsMatcher IsAbstractClassTemplate(std::string const &str, - std::string const &tmplt, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher(CasedString( - fmt::format("abstract \"{}<{}>\"", str, tmplt), caseSensitivity)); -} - -ContainsMatcher IsBaseClass(std::string const &base, std::string const &sub, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher(CasedString(base + " <|-- " + sub, caseSensitivity)); -} - -namespace mermaid { -ContainsMatcher IsBaseClass(std::string const &base, std::string const &sub, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher(CasedString(base + " <|-- " + sub, caseSensitivity)); -} -} - -ContainsMatcher IsInnerClass(std::string const &parent, - std::string const &inner, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher( - CasedString(inner + " --+ " + parent, caseSensitivity)); -} - -namespace mermaid { -ContainsMatcher IsInnerClass(std::string const &parent, - std::string const &inner, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher( - CasedString(parent + " ()-- " + inner + " : ", caseSensitivity)); -} -} - -ContainsMatcher IsAssociation(std::string const &from, std::string const &to, - std::string const &label = "", std::string multiplicity_source = "", - std::string multiplicity_dest = "", std::string style = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - std::string format_string = "{}"; - if (!multiplicity_source.empty()) - format_string += " \"" + multiplicity_source + "\""; - - format_string += fmt::format(" -{}->", style); - - if (!multiplicity_dest.empty()) - format_string += " \"" + multiplicity_dest + "\""; - - format_string += " {}"; - - if (!label.empty()) { - format_string += " : {}"; - return ContainsMatcher(CasedString( - fmt::format(fmt::runtime(format_string), from, to, label), - caseSensitivity)); + if (e["type"] == "namespace" || e["type"] == "folder") { + auto maybe_e = get_element_by_id(e, id); + if (maybe_e) + return maybe_e; + } } - else - return ContainsMatcher( - CasedString(fmt::format(fmt::runtime(format_string), from, to), - caseSensitivity)); + + return {}; } -ContainsMatcher IsComposition(std::string const &from, std::string const &to, - std::string const &label, std::string multiplicity_source = "", - std::string multiplicity_dest = "", std::string style = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +std::optional get_element( + const nlohmann::json &j, const std::string &name) { - std::string format_string = "{}"; - if (!multiplicity_source.empty()) - format_string += " \"" + multiplicity_source + "\""; + if (!j.contains("elements")) + return {}; - format_string += fmt::format(" *-{}-", style); + for (const nlohmann::json &e : j["elements"]) { + if (e["display_name"] == name) + return {e}; - if (!multiplicity_dest.empty()) - format_string += " \"" + multiplicity_dest + "\""; + if (e["type"] == "namespace" || e["type"] == "folder" || + e["type"] == "directory" || e["type"] == "module") { + auto maybe_e = get_element(e, name); + if (maybe_e) + return maybe_e; + } + } - format_string += " {} : {}"; - - return ContainsMatcher( - CasedString(fmt::format(fmt::runtime(format_string), from, to, label), - caseSensitivity)); + return {}; } -ContainsMatcher IsAggregation(std::string const &from, std::string const &to, - std::string const &label, std::string multiplicity_source = "", - std::string multiplicity_dest = "", std::string style = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +std::optional get_element( + const json_t &src, const std::string &name) { - std::string format_string = "{}"; - if (!multiplicity_source.empty()) - format_string += " \"" + multiplicity_source + "\""; - - format_string += fmt::format(" o-{}-", style); - - if (!multiplicity_dest.empty()) - format_string += " \"" + multiplicity_dest + "\""; - - format_string += " {} : {}"; - - return ContainsMatcher( - CasedString(fmt::format(fmt::runtime(format_string), from, to, label), - caseSensitivity)); + return get_element(src.src, name); } -ContainsMatcher IsInstantiation(std::string const &from, std::string const &to, - std::string style = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +std::optional get_participant( + const nlohmann::json &j, const std::string &name) { - return ContainsMatcher(CasedString( - fmt::format("{} .{}.|> {}", to, style, from), caseSensitivity)); + if (!j.contains("participants")) + return {}; + + for (const nlohmann::json &e : j.at("participants")) { + if (e["display_name"] == name) + return {e}; + } + + return {}; } -ContainsMatcher IsDependency(std::string const &from, std::string const &to, - std::string style = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +auto get_relationship(const nlohmann::json &j, const nlohmann::json &from, + const nlohmann::json &to, const std::string &type, const std::string &label) { - return ContainsMatcher(CasedString( - fmt::format("{} .{}.> {}", from, style, to), caseSensitivity)); + return std::find_if(j["relationships"].begin(), j["relationships"].end(), + [&](const auto &it) { + auto match = (it["source"] == from) && (it["destination"] == to) && + (it["type"] == type); + + if (match && label.empty()) + return true; + + if (match && (label == it["label"])) + return true; + + return false; + }); } -namespace mermaid { -ContainsMatcher IsPackageDependency(std::string const &from, - std::string const &to, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +auto get_relationship(const nlohmann::json &j, const std::string &from, + const std::string &to, const std::string &type, + const std::string &label = {}) { - return ContainsMatcher( - CasedString(fmt::format("{} -.-> {}", from, to), caseSensitivity)); -} -ContainsMatcher IsIncludeDependency(std::string const &from, - std::string const &to, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher( - CasedString(fmt::format("{} -.-> {}", from, to), caseSensitivity)); -} + auto source = get_element(j, from); + auto destination = get_element(j, to); + + if (!(source && destination)) + return j["relationships"].end(); + + return get_relationship( + j, source->at("id"), destination->at("id"), type, label); } -ContainsMatcher IsConstraint(std::string const &from, std::string const &to, - std::string const &label = {}, std::string style = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +std::string expand_name(const nlohmann::json &j, const std::string &name) { - if (label.empty()) - return ContainsMatcher(CasedString( - fmt::format("{} .{}.> {}", from, style, to), caseSensitivity)); - else - return ContainsMatcher( - CasedString(fmt::format("{} .{}.> {} : {}", from, style, to, label), - caseSensitivity)); + return name; } -ContainsMatcher IsConceptRequirement(std::string const &cpt, - std::string const &requirement, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> bool diagram_source_t::contains(std::string name) const { - return ContainsMatcher(CasedString(requirement, caseSensitivity)); + return util::contains(src, name); } -namespace mermaid { -ContainsMatcher IsConstraint(std::string const &from, std::string const &to, - std::string label = {}, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> +int64_t diagram_source_t::find( + const std::string &pattern, int64_t offset) const { - util::replace_all(label, "<", "<"); - util::replace_all(label, ">", ">"); - util::replace_all(label, "(", "("); - util::replace_all(label, ")", ")"); - util::replace_all(label, "##", "::"); - util::replace_all(label, "{", "{"); - util::replace_all(label, "}", "}"); + std::regex pattern_regex{pattern}; - if (label.empty()) - return ContainsMatcher( - CasedString(fmt::format("{} ..> {}", from, to), caseSensitivity)); - else - return ContainsMatcher(CasedString( - fmt::format("{} ..> {} : {}", from, to, label), caseSensitivity)); + std::smatch base_match; + auto offset_it = src.begin(); + std::advance(offset_it, offset); + bool found = + std::regex_search(offset_it, src.end(), base_match, pattern_regex); + if (!found) + return -1; + + return base_match.position(0); } -ContainsMatcher IsConceptRequirement(std::string const &cpt, - std::string requirement, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> +bool diagram_source_t::search(const std::string &pattern) const { - util::replace_all(requirement, "<", "<"); - util::replace_all(requirement, ">", ">"); - util::replace_all(requirement, "(", "("); - util::replace_all(requirement, ")", ")"); - util::replace_all(requirement, "##", "::"); - util::replace_all(requirement, "{", "{"); - util::replace_all(requirement, "}", "}"); - - return ContainsMatcher(CasedString(requirement, caseSensitivity)); -} + return find(pattern) > -1; } -ContainsMatcher IsLayoutHint(std::string const &from, std::string const &hint, - std::string const &to, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> +bool diagram_source_t::contains(std::string name) const { - return ContainsMatcher(CasedString( - fmt::format("{} -[hidden]{}- {}", from, hint, to), caseSensitivity)); + return false; } -ContainsMatcher HasComment(std::string const &comment, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> std::string diagram_source_t::to_string() const { - return ContainsMatcher( - CasedString(fmt::format("' {}", comment), caseSensitivity)); + return src; } -namespace mermaid { -ContainsMatcher HasComment(std::string const &comment, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> std::string diagram_source_t::to_string() const { - return ContainsMatcher( - CasedString(fmt::format("%% {}", comment), caseSensitivity)); -} + return src.dump(2); } -ContainsMatcher HasNote(std::string const &cls, std::string const &position, - std::string const ¬e = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +struct QualifiedName { + QualifiedName(const char *n) + : name{n} + { + } + + QualifiedName(std::string_view n) + : name{n} + { + } + + QualifiedName(std::string_view ns_, std::string_view n) + : ns{ns_} + , name{n} + { + } + + QualifiedName(const char *ns_, const char *n) + : ns{ns_} + , name{n} + { + } + + operator std::string() const { return str(); } + + std::string str(bool generate_packages = false) const + { + if (ns && !generate_packages) + return fmt::format("{}::{}", ns.value(), name); + + return name; + } + + std::optional ns; + std::string name; +}; + +struct Message { + template + Message(QualifiedName f, QualifiedName t, std::string m, Attrs &&...attrs) + : from{std::move(f)} + , to{std::move(t)} + , message{std::move(m)} + , is_static{has_type()} + , is_incontrolcondition{has_type()} + , is_response{has_type()} + , is_cuda_kernel{has_type()} + , is_cuda_device{has_type()} + { + } + + template + Message(Entrypoint &&e, QualifiedName t, std::string m, Attrs &&...attrs) + : Message(QualifiedName{""}, std::move(t), {}, + std::forward(attrs)...) + { + is_entrypoint = true; + } + + template + Message(Exitpoint &&e, QualifiedName t, Attrs &&...attrs) + : Message(QualifiedName{""}, std::move(t), {}, + std::forward(attrs)...) + { + is_exitpoint = true; + } + + QualifiedName from; + QualifiedName to; + std::string message; + std::optional return_type; + + bool is_static{false}; + bool is_entrypoint{false}; + bool is_exitpoint{false}; + bool is_incontrolcondition{false}; + bool is_response{false}; + bool is_cuda_kernel{false}; + bool is_cuda_device{false}; +}; + +/// +/// The following functions declarations define various checks on generated +/// diagrams. +/// They must be specialized for each diagram format (DiagramType) separately. +/// +/// @defgroup Test Cases diagram checks +/// @{ +/// + +// Check if generated diagram source starts with pattern +template +bool StartsWith(const DiagramType &d, std::string pattern); + +// Check if generated diagram source ends with pattern +template +bool EndsWith(const DiagramType &d, std::string pattern); + +template +bool HasTitle(const DiagramType &d, std::string const &str); + +// Check if generated diagram contains a specified enum +template +bool IsEnum(const DiagramType &d, QualifiedName name); + +// Check if generated diagram contains a specified union +template +bool IsUnion(const DiagramType &d, QualifiedName name); + +// Check if generated diagram contains a specified class +template +bool IsClass(const DiagramType &d, QualifiedName name); + +// Check if generated diagram contains a specified class template +template +bool IsClassTemplate(const DiagramType &d, QualifiedName name); + +template +bool IsAbstractClassTemplate(const DiagramType &d, QualifiedName name); + +// Check if generated diagram contains a specified abstract class +template +bool IsAbstractClass(const DiagramType &d, QualifiedName name); + +// Check if generated diagram contains a specified class +template +bool IsBaseClass( + const DiagramType &d, QualifiedName base, QualifiedName subclass); + +template +bool IsInnerClass( + const DiagramType &d, std::string const &parent, std::string const &inner); + +template +bool IsMethod(const DiagramType &d, const std::string &cls, + const std::string &name, const std::string &type = "void", + const std::string ¶ms = ""); + +template +bool IsField(const DiagramType &d, QualifiedName cls, std::string const &name, + std::string type = "void"); + +template +bool IsAssociation(const DiagramType &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = ""); + +template +bool IsComposition(const DiagramType &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = ""); + +template +bool IsAggregation(const DiagramType &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = ""); + +template +bool IsInstantiation(const DiagramType &d, std::string const &from, + std::string const &to, std::string style = ""); + +template +bool IsDependency(const DiagramType &d, QualifiedName from, QualifiedName to, + std::string style = ""); + +template +bool IsFriend( + const DiagramType &d, std::string const &from, std::string const &to); + +template +bool IsPackageDependency( + const DiagramType &d, std::string const &from, std::string const &to); + +template +bool IsIncludeDependency( + const DiagramType &d, std::string const &from, std::string const &to); + +template +bool IsConstraint(const DiagramType &d, QualifiedName from, QualifiedName to, + std::string label = {}, std::string style = ""); + +template +bool IsConcept(const DiagramType &d, QualifiedName cpt); + +template +bool IsConceptParameterList( + const DiagramType &d, std::string const &cpt, std::string param); + +template +bool IsConceptRequirement( + const DiagramType &d, std::string const &cpt, std::string requirement); + +template +bool IsLayoutHint(const DiagramType &d, std::string const &from, + std::string const &hint, std::string const &to); + +template +bool HasComment(const DiagramType &d, std::string const &comment); + +template +bool HasNote(const DiagramType &d, std::string const &cls, + std::string const &position, std::string const ¬e = ""); + +template +bool HasPackageNote(const DiagramType &d, std::string const &cls, + std::string const &position, std::string const ¬e = ""); + +template +bool HasMessageComment( + const DiagramType &d, std::string const &alias, std::string const ¬e); + +template +bool HasMemberNote(const DiagramType &d, std::string const &cls, + std::string const &member, std::string const &position, + std::string const ¬e = ""); + +template +bool HasLink(const DiagramType &d, std::string const &alias, + std::string const &link, std::string const &tooltip); + +template +bool HasMemberLink(const DiagramType &d, std::string const &method, + std::string const &link, std::string const &tooltip); + +template +bool IsFolder(const DiagramType &d, std::string const &path); + +template +bool IsFile(const DiagramType &d, std::string const &str); + +template +bool IsSystemHeader(const DiagramType &d, std::string const &str); + +template +bool IsHeaderDependency(const DiagramType &d, std::string const &from, + std::string const &to, std::string style = ""); + +template +bool IsSystemHeaderDependency(const DiagramType &d, std::string const &from, + std::string const &to, std::string style = ""); + +template +bool IsNamespacePackage(const DiagramType &d, Args... args); + +template +bool IsDirectoryPackage(const DiagramType &d, Args... args); + +template +bool IsModulePackage(const DiagramType &d, Args... args); + +template +bool IsDeprecated(const DiagramType &d, std::string const &str); + +template +int64_t FindMessage(const DiagramType &d, const Message &msg, + int64_t offset = 0, bool fail = true); + +template +bool HasMessage(const DiagramType &d, const Message &msg) { - return ContainsMatcher(CasedString( - fmt::format("note {} of {}", position, cls), caseSensitivity)); + return FindMessage(d, msg, 0, false) >= 0; } -auto HasMessageComment(std::string const &alias, std::string const ¬e, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template +bool MessageOrder(const DiagramType &d, std::vector messages) { - return Catch::Matchers::Matches( - std::string("note over ") + alias + "\\n" + note + "\\n" + "end note", - caseSensitivity); + std::vector order; + int64_t offset{0}; + order.reserve(messages.size()); + std::transform(messages.begin(), messages.end(), std::back_inserter(order), + [&d, &offset](const auto &m) { + offset = FindMessage(d, m, offset); + return offset; + }); + bool are_messages_in_order = std::is_sorted(order.begin(), order.end()); + + if (!are_messages_in_order) { + FAIL(fmt::format( + "Messages are not in order: \n[{}]", fmt::join(order, ",\n"))); + return false; + } + + return true; } -namespace mermaid { -auto HasMessageComment(std::string const &alias, std::string const ¬e, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template +bool MessageChainsOrder( + const DiagramType &d, std::vector> message_chains) { - return Catch::Matchers::Matches( - std::string("note over ") + alias + ": " + note, caseSensitivity); + // Try to match each chain to each sequence - sequence order depends + // on platform and LLVM version + for (const auto &message_chain : message_chains) { + if (!MessageOrder(d, message_chain)) + return false; + } + + return true; } -ContainsMatcher HasNote(std::string const &cls, - std::string const &position = "", std::string const ¬e = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template +bool IsParticipant( + const DiagramType &d, const std::string &name, const std::string &type); + +template +bool IsFunctionParticipant(const DiagramType &d, const std::string &name) { - return ContainsMatcher( - CasedString(fmt::format("note for {}", cls), caseSensitivity)); -} -ContainsMatcher HasPackageNote(std::string const &cls, - std::string const &position = "", std::string const ¬e = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - return ContainsMatcher( - CasedString(fmt::format("-.- {}", cls), caseSensitivity)); -} + return IsParticipant(d, name, "function"); } -ContainsMatcher HasMemberNote(std::string const &cls, std::string const &member, - std::string const &position, std::string const ¬e = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template +bool IsFunctionTemplateParticipant( + const DiagramType &d, const std::string &name) { - return ContainsMatcher( - CasedString(fmt::format("note {} of {}::{}", position, cls, member), - caseSensitivity)); + return IsParticipant(d, name, "function_template"); } -ContainsMatcher HasLink(std::string const &alias, std::string const &link, - std::string const &tooltip, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template +bool IsClassParticipant(const DiagramType &d, const std::string &name) { - return ContainsMatcher(CasedString( - fmt::format("{} [[{}{{{}}}]]", alias, link, tooltip), caseSensitivity)); + return IsParticipant(d, name, "class"); } -namespace mermaid { -ContainsMatcher HasLink(std::string const &alias, std::string const &link, - std::string const &tooltip, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template +bool IsFileParticipant(const DiagramType &d, const std::string &name) { - return ContainsMatcher(CasedString( - fmt::format("click {} href \"{}\" \"{}\"", alias, link, tooltip), - caseSensitivity)); -} + return IsParticipant(d, name, "file"); } -ContainsMatcher HasMemberLink(std::string const &method, - std::string const &link, std::string const &tooltip, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +/// +/// @} +/// + +template <> bool StartsWith(const plantuml_t &d, std::string pattern) { - return ContainsMatcher( - CasedString(fmt::format("{} [[[{}{{{}}}]]]", method, link, tooltip), - caseSensitivity)); + return util::starts_with(d.src, pattern); +} + +template <> bool EndsWith(const plantuml_t &d, std::string pattern) +{ + return util::ends_with(d.src, pattern); +} + +template <> bool HasTitle(const plantuml_t &d, std::string const &str) +{ + return d.contains("title " + str); +} + +template <> bool IsEnum(const plantuml_t &d, QualifiedName enm) +{ + return d.contains( + fmt::format("enum {}", d.get_alias(enm.str(d.generate_packages)))); +} + +template <> bool IsUnion(const plantuml_t &d, QualifiedName cls) +{ + return d.contains(fmt::format( + "class {} <>", d.get_alias(cls.str(d.generate_packages)))); +} + +template <> bool IsClass(const plantuml_t &d, QualifiedName cls) +{ + return d.contains( + fmt::format("class {}", d.get_alias(cls.str(d.generate_packages)))); +} + +template <> bool IsClassTemplate(const plantuml_t &d, QualifiedName cls) +{ + return d.contains( + fmt::format("class \"{}\"", cls.str(d.generate_packages))); +} + +template <> bool IsAbstractClassTemplate(const plantuml_t &d, QualifiedName cls) +{ + return d.contains( + fmt::format("abstract \"{}\"", cls.str(d.generate_packages))); +} + +template <> bool IsAbstractClass(const plantuml_t &d, QualifiedName cls) +{ + return d.contains( + fmt::format("abstract {}", d.get_alias(cls.str(d.generate_packages)))); +} + +template <> +bool IsBaseClass( + const plantuml_t &d, QualifiedName base, QualifiedName subclass) +{ + return d.contains( + fmt::format("{} <|-- {}", d.get_alias(base.str(d.generate_packages)), + d.get_alias(subclass.str(d.generate_packages)))); +} + +template <> +bool IsInnerClass( + const plantuml_t &d, std::string const &parent, std::string const &inner) +{ + return d.contains(d.get_alias(inner) + " --+ " + d.get_alias(parent)); } template -ContainsMatcher IsMethod(std::string const &name, - std::string const &type = "void", std::string const ¶ms = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +bool IsMethod(const plantuml_t &d, std::string const &cls, + std::string const &name, std::string const &type = "void", + std::string const ¶ms = "") { std::string pattern; if constexpr (has_type()) @@ -933,14 +875,467 @@ ContainsMatcher IsMethod(std::string const &name, pattern += " : " + type; - return ContainsMatcher(CasedString(pattern, caseSensitivity)); + return d.contains(pattern); } -namespace mermaid { template -ContainsMatcher IsMethod(std::string const &name, std::string type = "void", - std::string const ¶ms = "", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +bool IsField(const plantuml_t &d, QualifiedName cls, std::string const &name, + std::string type) +{ + std::string pattern; + if constexpr (has_type()) + pattern += "{static} "; + + if constexpr (has_type()) + pattern = "+"; + else if constexpr (has_type()) + pattern = "#"; + else + pattern = "-"; + + pattern += name; + + return d.contains(pattern + " : " + type); +} + +template +bool IsAssociation(const plantuml_t &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = "") +{ + auto from_id = d.get_alias(from); + auto to_id = d.get_alias(to); + + std::string format_string = "{}"; + if (!multiplicity_source.empty()) + format_string += " \"" + multiplicity_source + "\""; + + format_string += fmt::format(" -{}->", style); + + if (!multiplicity_dest.empty()) + format_string += " \"" + multiplicity_dest + "\""; + + format_string += " {}"; + + if (!label.empty()) { + std::string label_prefix; + if constexpr (has_type()) + label_prefix = "+"; + else if constexpr (has_type()) + label_prefix = "#"; + else + label_prefix = "-"; + + format_string += " : {}{}"; + return d.contains(fmt::format( + fmt::runtime(format_string), from_id, to_id, label_prefix, label)); + } + + return d.contains(fmt::format(fmt::runtime(format_string), from_id, to_id)); +} + +template +bool IsComposition(const plantuml_t &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = "") +{ + std::string label_prefix; + if constexpr (has_type()) + label_prefix = "+"; + else if constexpr (has_type()) + label_prefix = "#"; + else + label_prefix = "-"; + + std::string format_string = "{}"; + if (!multiplicity_source.empty()) + format_string += " \"" + multiplicity_source + "\""; + + format_string += fmt::format(" *-{}-", style); + + if (!multiplicity_dest.empty()) + format_string += " \"" + multiplicity_dest + "\""; + + format_string += " {} : {}{}"; + + return d.contains(fmt::format(fmt::runtime(format_string), + d.get_alias(from), d.get_alias(to), label_prefix, label)); +} + +template +bool IsAggregation(const plantuml_t &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = "") +{ + std::string label_prefix; + if constexpr (has_type()) + label_prefix = "+"; + else if constexpr (has_type()) + label_prefix = "#"; + else + label_prefix = "-"; + + std::string format_string = "{}"; + if (!multiplicity_source.empty()) + format_string += " \"" + multiplicity_source + "\""; + + format_string += fmt::format(" o-{}-", style); + + if (!multiplicity_dest.empty()) + format_string += " \"" + multiplicity_dest + "\""; + + format_string += " {} : {}{}"; + + return d.contains(fmt::format(fmt::runtime(format_string), + d.get_alias(from), d.get_alias(to), label_prefix, label)); +} + +template <> +bool IsInstantiation(const plantuml_t &d, std::string const &from, + std::string const &to, std::string style) +{ + return d.contains( + fmt::format("{} .{}.|> {}", d.get_alias(to), style, d.get_alias(from))); +} + +template <> +bool IsDependency(const plantuml_t &d, QualifiedName from, QualifiedName to, + std::string style) +{ + return d.contains(fmt::format( + "{} .{}.> {}", d.get_alias(from), style, d.get_alias(to))) || + d.contains(fmt::format("{} .{}.> {}", d.get_alias(from.name), style, + d.get_alias(to.name))); +} + +template +bool IsFriend( + const plantuml_t &d, std::string const &from, std::string const &to) +{ + std::string pattern; + + if constexpr (has_type()) + pattern = "+"; + else if constexpr (has_type()) + pattern = "#"; + else + pattern = "-"; + + return d.contains(fmt::format("{} <.. {} : {}<>", d.get_alias(from), + d.get_alias(to), pattern)); +} + +template <> +bool IsPackageDependency( + const plantuml_t &d, std::string const &from, std::string const &to) +{ + return d.contains( + fmt::format("{} .{}.> {}", d.get_alias(from), "", d.get_alias(to))); +} + +template <> +bool IsIncludeDependency( + const plantuml_t &d, std::string const &from, std::string const &to) +{ + return d.contains( + fmt::format("{} .{}.> {}", d.get_alias(from), "", d.get_alias(to))); +} + +template <> +bool IsConstraint(const plantuml_t &d, QualifiedName from, QualifiedName to, + std::string label, std::string style) +{ + if (label.empty()) + return d.contains(fmt::format("{} .{}.> {}", d.get_alias(from.name), + style, d.get_alias(to.name))); + + return d.contains(fmt::format("{} .{}.> {} : {}", d.get_alias(from.name), + style, d.get_alias(to.name), label)); +} + +template <> bool IsConcept(const plantuml_t &d, QualifiedName cpt) +{ + return d.contains("class " + d.get_alias(cpt) + " <>") || + d.contains("class " + d.get_alias(cpt.name) + " <>"); +} + +template <> +bool IsConceptRequirement( + const plantuml_t &d, std::string const &cpt, std::string requirement) +{ + return d.contains(requirement); +} + +template <> +bool IsConceptParameterList( + const plantuml_t &d, std::string const &cpt, std::string params) +{ + return d.contains(params); +} + +template <> +bool IsLayoutHint(const plantuml_t &d, std::string const &from, + std::string const &hint, std::string const &to) +{ + return d.contains(fmt::format( + "{} -[hidden]{}- {}", d.get_alias(from), hint, d.get_alias(to))); +} + +template <> bool HasComment(const plantuml_t &d, std::string const &comment) +{ + return d.contains(fmt::format("' {}", comment)); +} + +template <> +bool HasNote(const plantuml_t &d, std::string const &cls, + std::string const &position, std::string const ¬e) +{ + return d.contains(fmt::format("note {} of {}", position, d.get_alias(cls))); +} + +template <> +bool HasMemberNote(const plantuml_t &d, std::string const &cls, + std::string const &member, std::string const &position, + std::string const ¬e) +{ + return d.contains( + fmt::format("note {} of {}::{}", position, d.get_alias(cls), member)); +} + +template <> +bool HasPackageNote(const plantuml_t &d, std::string const &cls, + std::string const &position, std::string const ¬e) +{ + return d.contains(fmt::format("note {} of {}", position, d.get_alias(cls))); +} + +template <> +bool HasLink(const plantuml_t &d, std::string const &element, + std::string const &link, std::string const &tooltip) +{ + return d.contains( + fmt::format("{} [[{}{{{}}}]]", d.get_alias(element), link, tooltip)); +} + +template <> +bool HasMemberLink(const plantuml_t &d, std::string const &method, + std::string const &link, std::string const &tooltip) +{ + return d.contains(fmt::format("{} [[[{}{{{}}}]]]", method, link, tooltip)); +} + +template <> bool IsFolder(const plantuml_t &d, std::string const &path) +{ + return d.contains("folder \"" + util::split(path, "/").back() + "\""); +} + +template <> bool IsFile(const plantuml_t &d, std::string const &path) +{ + return d.contains("file \"" + util::split(path, "/").back() + "\""); +} + +template <> bool IsSystemHeader(const plantuml_t &d, std::string const &path) +{ + return d.contains("file \"" + path + "\""); +} + +template <> +bool IsHeaderDependency(const plantuml_t &d, std::string const &from, + std::string const &to, std::string style) +{ + assert(d.diagram_type == common::model::diagram_t::kInclude); + + return d.contains( + fmt::format("{} --> {}", d.get_alias(util::split(from, "/").back()), + d.get_alias(util::split(to, "/").back()))); +} + +template <> +bool IsSystemHeaderDependency(const plantuml_t &d, std::string const &from, + std::string const &to, std::string style) +{ + assert(d.diagram_type == common::model::diagram_t::kInclude); + + return d.contains( + fmt::format("{} ..> {}", d.get_alias(util::split(from, "/").back()), + d.get_alias(util::split(to, "/").back()))); +} + +template auto get_last(Args &&...args) +{ + return std::get(std::forward_as_tuple(args...)); +} + +template +bool IsNamespacePackage(const plantuml_t &d, Args... args) +{ + const auto &name = get_last(args...); + return d.contains("package [" + name + "]"); +} + +template +bool IsDirectoryPackage(const plantuml_t &d, Args... args) +{ + const auto &name = get_last(args...); + return d.contains("package [" + name + "]"); +} + +template +bool IsModulePackage(const plantuml_t &d, Args... args) +{ + const auto &name = get_last(args...); + return d.contains("package [" + name + "]"); +} + +template <> bool IsDeprecated(const plantuml_t &d, const std::string &name) +{ + return d.contains(d.get_alias(name) + " <> "); +} + +template <> +int64_t FindMessage( + const plantuml_t &d, const Message &msg, int64_t offset, bool fail) +{ + auto msg_str = msg.message; + util::replace_all(msg_str, "(", "\\("); + util::replace_all(msg_str, ")", "\\)"); + util::replace_all(msg_str, "*", "\\*"); + util::replace_all(msg_str, "[", "\\["); + util::replace_all(msg_str, "]", "\\]"); + util::replace_all(msg_str, "+", "\\+"); + + if (msg.is_cuda_kernel) + msg_str = fmt::format("<< CUDA Kernel >>\\\\n{}", msg_str); + if (msg.is_cuda_device) + msg_str = fmt::format("<< CUDA Device >>\\\\n{}", msg_str); + + std::string style; + if (msg.is_static) + style = "__"; + + std::string call_pattern{"__INVALID__"}; + + if (msg.is_entrypoint) { + call_pattern = + fmt::format("\\[-> {} : {}", d.get_alias(msg.to), msg_str); + } + else if (msg.is_exitpoint) { + call_pattern = fmt::format("\\[<-- {}", d.get_alias(msg.to)); + } + else if (msg.is_incontrolcondition) { + call_pattern = fmt::format( + "{} {} {} " + "(\\[\\[.*\\]\\] )?: \\*\\*\\[\\*\\*{}{}{}\\*\\*\\]\\*\\*", + d.get_alias(msg.from), "->", d.get_alias(msg.to), style, msg_str, + style); + } + else if (msg.is_response) { + call_pattern = fmt::format("{} {} {} : //{}//", d.get_alias(msg.from), + "-->", d.get_alias(msg.to), msg_str); + } + else { + call_pattern = fmt::format("{} {} {} " + "(\\[\\[.*\\]\\] )?: {}{}{}", + d.get_alias(msg.from), "->", d.get_alias(msg.to), style, msg_str, + style); + } + + auto match_offset = d.find(call_pattern, offset); + + if (match_offset < 0) { + if (fail) + FAIL(fmt::format("Missing message: {} -> {} {} ({})", + msg.from.str(), msg.to.str(), msg.message, call_pattern)); + return -1; + } + + return match_offset + offset; +} + +template <> +bool HasMessageComment(const plantuml_t &d, std::string const &participant, + std::string const ¬e) +{ + std::string note_escaped{note}; + util::replace_all(note_escaped, "(", "\\("); + util::replace_all(note_escaped, ")", "\\)"); + + return d.search(fmt::format("note over {}\\n{}\\nend note", + d.get_alias(participant), note_escaped)); +} + +template <> +bool IsParticipant( + const plantuml_t &d, const std::string &name, const std::string &type) +{ + return d.contains( + fmt::format("participant \"{}\" as ", name, d.get_alias(name))); +} + +// +// MermaidJS test helpers +// + +template <> bool HasTitle(const mermaid_t &d, std::string const &str) +{ + return d.contains("title: " + str); +} + +template <> bool IsEnum(const mermaid_t &d, QualifiedName enm) +{ + return d.search(std::string("class ") + d.get_alias(enm) + + " \\{\\n\\s+<>"); +} + +template <> bool IsUnion(const mermaid_t &d, QualifiedName cls) +{ + return d.search( + std::string("class ") + d.get_alias(cls) + " \\{\\n\\s+<>"); +} + +template <> bool IsClass(const mermaid_t &d, QualifiedName cls) +{ + return d.contains(fmt::format("class {}", d.get_alias(cls))); +} + +template <> bool IsClassTemplate(const mermaid_t &d, QualifiedName cls) +{ + return d.contains(fmt::format("class {}", d.get_alias(cls))); +} + +template <> bool IsAbstractClassTemplate(const mermaid_t &d, QualifiedName cls) +{ + return d.search( + std::string("class ") + d.get_alias(cls) + " \\{\\n\\s+<>"); +} + +template <> bool IsAbstractClass(const mermaid_t &d, QualifiedName name) +{ + return d.search( + std::string("class ") + d.get_alias(name) + " \\{\\n\\s+<>"); +} + +template <> +bool IsBaseClass(const mermaid_t &d, QualifiedName base, QualifiedName subclass) +{ + return d.contains( + fmt::format("{} <|-- {}", d.get_alias(base), d.get_alias(subclass))); +} + +template <> +bool IsInnerClass( + const mermaid_t &d, std::string const &parent, std::string const &inner) +{ + return d.contains(d.get_alias(parent) + " ()-- " + d.get_alias(inner)); +} + +template +bool IsMethod(const mermaid_t &d, std::string const &cls, + std::string const &name, std::string type = "void", + std::string const ¶ms = "") { std::string pattern; @@ -989,36 +1384,12 @@ ContainsMatcher IsMethod(std::string const &name, std::string type = "void", if constexpr (has_type()) pattern += "$"; - return ContainsMatcher(CasedString(pattern, caseSensitivity)); -} + return d.contains(pattern); } template -ContainsMatcher IsField(std::string const &name, - std::string const &type = "void", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) -{ - std::string pattern; - if constexpr (has_type()) - pattern += "{static} "; - - if constexpr (has_type()) - pattern = "+"; - else if constexpr (has_type()) - pattern = "#"; - else - pattern = "-"; - - pattern += name; - - return ContainsMatcher( - CasedString(pattern + " : " + type, caseSensitivity)); -} - -namespace mermaid { -template -ContainsMatcher IsField(std::string const &name, std::string type = "void", - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +bool IsField(const mermaid_t &d, QualifiedName cls, std::string const &name, + std::string type) { std::string pattern; if constexpr (has_type()) @@ -1041,14 +1412,150 @@ ContainsMatcher IsField(std::string const &name, std::string type = "void", util::replace_all(type, "{", "{"); util::replace_all(type, "}", "}"); - return ContainsMatcher( - CasedString(pattern + " : " + type, caseSensitivity)); -} + return d.contains(pattern + " : " + type); } template -ContainsMatcher IsFriend(std::string const &from, std::string const &to, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +bool IsAssociation(const mermaid_t &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = "") +{ + auto from_id = d.get_alias(from); + auto to_id = d.get_alias(to); + + std::string label_prefix; + if constexpr (has_type()) + label_prefix = "+"; + else if constexpr (has_type()) + label_prefix = "#"; + else + label_prefix = "-"; + + std::string format_string = "{}"; + if (!multiplicity_source.empty()) + format_string += " \"" + multiplicity_source + "\""; + + format_string += " -->"; + + if (!multiplicity_dest.empty()) + format_string += " \"" + multiplicity_dest + "\""; + + format_string += " {}"; + + if (!label.empty()) { + format_string += " : {}{}"; + return d.contains(fmt::format( + fmt::runtime(format_string), from_id, to_id, label_prefix, label)); + } + + return d.contains(fmt::format(fmt::runtime(format_string), from_id, to_id)); +} + +template +bool IsComposition(const mermaid_t &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = "") +{ + std::string label_prefix; + if constexpr (has_type()) + label_prefix = "+"; + else if constexpr (has_type()) + label_prefix = "#"; + else + label_prefix = "-"; + + std::string format_string = "{}"; + if (!multiplicity_source.empty()) + format_string += " \"" + multiplicity_source + "\""; + + format_string += fmt::format(" *--", style); + + if (!multiplicity_dest.empty()) + format_string += " \"" + multiplicity_dest + "\""; + + format_string += " {} : {}{}"; + + return d.contains(fmt::format(fmt::runtime(format_string), + d.get_alias(from), d.get_alias(to), label_prefix, label)); +} + +template +bool IsAggregation(const mermaid_t &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = "") +{ + std::string label_prefix; + if constexpr (has_type()) + label_prefix = "+"; + else if constexpr (has_type()) + label_prefix = "#"; + else + label_prefix = "-"; + + std::string format_string = "{}"; + if (!multiplicity_source.empty()) + format_string += " \"" + multiplicity_source + "\""; + + format_string += " o--"; + + if (!multiplicity_dest.empty()) + format_string += " \"" + multiplicity_dest + "\""; + + format_string += " {} : {}{}"; + + return d.contains(fmt::format(fmt::runtime(format_string), + d.get_alias(from), d.get_alias(to), label_prefix, label)); +} + +template <> +bool IsInstantiation(const mermaid_t &d, std::string const &from, + std::string const &to, std::string style) +{ + return d.contains( + fmt::format("{} ..|> {}", d.get_alias(to), d.get_alias(from))); +} + +template <> +bool IsDependency( + const mermaid_t &d, QualifiedName from, QualifiedName to, std::string style) +{ + if (d.diagram_type == common::model::diagram_t::kClass) { + return d.contains( + fmt::format("{} ..> {}", d.get_alias(from), d.get_alias(to))); + } + + return d.contains( + fmt::format("{} -.-> {}", d.get_alias(from), d.get_alias(to))); +} + +template <> +bool IsHeaderDependency(const mermaid_t &d, std::string const &from, + std::string const &to, std::string style) +{ + assert(d.diagram_type == common::model::diagram_t::kInclude); + + return d.contains( + fmt::format("{} --> {}", d.get_alias(util::split(from, "/").back()), + d.get_alias(util::split(to, "/").back()))); +} + +template <> +bool IsSystemHeaderDependency(const mermaid_t &d, std::string const &from, + std::string const &to, std::string style) +{ + assert(d.diagram_type == common::model::diagram_t::kInclude); + + return d.contains( + fmt::format("{} -.-> {}", d.get_alias(util::split(from, "/").back()), + d.get_alias(util::split(to, "/").back()))); +} + +template +bool IsFriend( + const mermaid_t &d, std::string const &from, std::string const &to) { std::string pattern; @@ -1059,82 +1566,265 @@ ContainsMatcher IsFriend(std::string const &from, std::string const &to, else pattern = "-"; - return ContainsMatcher( - CasedString(fmt::format("{} <.. {} : {}<>", from, to, pattern), - caseSensitivity)); + return d.contains(fmt::format( + "{} <.. {} : {}[friend]", d.get_alias(from), d.get_alias(to), pattern)); } -namespace mermaid { -template -ContainsMatcher IsFriend(std::string const &from, std::string const &to, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> +bool IsPackageDependency( + const mermaid_t &d, std::string const &from, std::string const &to) { - std::string pattern; - - if constexpr (has_type()) - pattern = "+"; - else if constexpr (has_type()) - pattern = "#"; - else - pattern = "-"; - - return ContainsMatcher( - CasedString(fmt::format("{} <.. {} : {}[friend]", from, to, pattern), - caseSensitivity)); -} + return d.contains( + fmt::format("{} -.-> {}", d.get_alias(from), "", d.get_alias(to))); } -ContainsMatcher IsPackage(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> +bool IsIncludeDependency( + const mermaid_t &d, std::string const &from, std::string const &to) { - return ContainsMatcher( - CasedString("package [" + str + "]", caseSensitivity)); + return d.contains( + fmt::format("{} -.-> {}", d.get_alias(from), "", d.get_alias(to))); } -namespace mermaid { -ContainsMatcher IsPackage(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> +bool IsConstraint(const mermaid_t &d, QualifiedName from, QualifiedName to, + std::string label, std::string style) { - return ContainsMatcher(CasedString("subgraph " + str, caseSensitivity)); -} + auto from_id = d.get_alias(from); + auto to_id = d.get_alias(to); + + if (label.empty()) + return d.contains(fmt::format("{} ..> {}", from_id, "", to_id)); + + util::replace_all(label, "<", "<"); + util::replace_all(label, ">", ">"); + util::replace_all(label, "(", "("); + util::replace_all(label, ")", ")"); + util::replace_all(label, "##", "::"); + util::replace_all(label, "{", "{"); + util::replace_all(label, "}", "}"); + + if (label.empty()) + return d.contains(fmt::format("{} ..> {}", from_id, to_id)); + + return d.contains(fmt::format("{} ..> {} : {}", from_id, to_id, label)); } -ContainsMatcher IsFolder(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> bool IsConcept(const mermaid_t &d, QualifiedName cpt) { - return ContainsMatcher( - CasedString("folder \"" + str + "\"", caseSensitivity)); + return d.search( + std::string("class ") + d.get_alias(cpt) + " \\{\\n\\s+<>"); } -ContainsMatcher IsFile(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> +bool IsConceptRequirement( + const mermaid_t &d, std::string const &cpt, std::string requirement) { - return ContainsMatcher( - CasedString("file \"" + str + "\"", caseSensitivity)); + util::replace_all(requirement, "<", "<"); + util::replace_all(requirement, ">", ">"); + util::replace_all(requirement, "##", "::"); + util::replace_all(requirement, "{", "{"); + util::replace_all(requirement, "}", "}"); + + return d.contains(requirement); } -namespace mermaid { -ContainsMatcher IsFolder(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> +bool IsConceptParameterList( + const mermaid_t &d, std::string const &cpt, std::string params) { - return ContainsMatcher(CasedString("subgraph " + str, caseSensitivity)); + util::replace_all(params, "<", "<"); + util::replace_all(params, ">", ">"); + util::replace_all(params, "##", "::"); + util::replace_all(params, "{", "{"); + util::replace_all(params, "}", "}"); + + return d.contains(params); } -ContainsMatcher IsFile(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> +bool IsLayoutHint(const mermaid_t &d, std::string const &from, + std::string const &hint, std::string const &to) { - return ContainsMatcher(CasedString(str + "[", caseSensitivity)); -} + return true; } -ContainsMatcher IsDeprecated(std::string const &str, - CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +template <> bool HasComment(const mermaid_t &d, std::string const &comment) { - return ContainsMatcher( - CasedString(str + " <> ", caseSensitivity)); + return d.contains(fmt::format("%% {}", comment)); } -namespace json { +template <> +bool HasNote(const mermaid_t &d, std::string const &cls, + std::string const &position, std::string const ¬e) +{ + if (d.diagram_type == common::model::diagram_t::kPackage) { + return d.contains(fmt::format("-.- {}", d.get_alias(cls))); + } + + return d.contains(fmt::format("note for {}", d.get_alias(cls))); +} + +template <> +bool HasMemberNote(const mermaid_t &d, std::string const &cls, + std::string const &member, std::string const &position, + std::string const ¬e) +{ + return d.contains( + fmt::format("note for {} \"{}\"", d.get_alias(cls), note)); +} + +template <> +bool HasPackageNote(const mermaid_t &d, std::string const &cls, + std::string const &position, std::string const ¬e) +{ + return d.contains(fmt::format("-.- {}", d.get_alias(cls))); +} + +template <> +bool HasLink(const mermaid_t &d, std::string const &element, + std::string const &link, std::string const &tooltip) +{ + return d.contains(fmt::format( + "click {} href \"{}\" \"{}\"", d.get_alias(element), link, tooltip)); +} + +template <> +bool HasMemberLink(const mermaid_t &d, std::string const &method, + std::string const &link, std::string const &tooltip) +{ + return true; +} + +template <> bool IsFolder(const mermaid_t &d, std::string const &path) +{ + return d.contains("subgraph " + d.get_alias(util::split(path, "/").back())); +} + +template <> bool IsFile(const mermaid_t &d, std::string const &path) +{ + return d.contains(d.get_alias(util::split(path, "/").back()) + "["); +} + +template <> bool IsSystemHeader(const mermaid_t &d, std::string const &path) +{ + return d.contains(d.get_alias(path) + "["); +} + +template +bool IsNamespacePackage(const mermaid_t &d, Args... args) +{ + if (d.diagram_type == class_diagram::model::diagram_t::kClass) { + std::vector toks{{args...}}; + return d.contains(fmt::format("[\"{}", fmt::join(toks, "::"))); + } + + const auto &name = get_last(args...); + return d.contains(fmt::format("subgraph {}", d.get_alias(name))); +} + +template +bool IsDirectoryPackage(const mermaid_t &d, Args... args) +{ + if (d.diagram_type == class_diagram::model::diagram_t::kClass) { + // MermaidJS does not support packages in class diagrams + return true; + } + + const auto &name = get_last(args...); + return d.contains("subgraph " + d.get_alias(name)); +} + +template +bool IsModulePackage(const mermaid_t &d, Args... args) +{ + if (d.diagram_type == class_diagram::model::diagram_t::kClass) { + // MermaidJS does not support packages in class diagrams + return true; + } + + const auto &name = get_last(args...); + return d.contains("subgraph " + d.get_alias(name)); +} + +template <> bool IsDeprecated(const mermaid_t &d, const std::string &name) +{ + return d.contains(d.get_alias(name)); +} + +template <> +int64_t FindMessage( + const mermaid_t &d, const Message &msg, int64_t offset, bool fail) +{ + auto msg_str = msg.message; + + util::replace_all(msg_str, "(", "\\("); + util::replace_all(msg_str, ")", "\\)"); + util::replace_all(msg_str, "*", "\\*"); + util::replace_all(msg_str, "[", "\\["); + util::replace_all(msg_str, "]", "\\]"); + util::replace_all(msg_str, "+", "\\+"); + + if (msg.is_cuda_kernel) + msg_str = fmt::format("<< CUDA Kernel >>
{}", msg_str); + if (msg.is_cuda_device) + msg_str = fmt::format("<< CUDA Device >>
{}", msg_str); + + std::string call_pattern{"__INVALID__"}; + + if (msg.is_entrypoint) { + call_pattern = + fmt::format("\\* ->> {} : {}", d.get_alias(msg.to), msg_str); + } + else if (msg.is_exitpoint) { + call_pattern = fmt::format("{} -->> \\*", d.get_alias(msg.to), msg_str); + } + else if (msg.is_incontrolcondition) { + call_pattern = fmt::format("{} {} {} : \\[{}\\]", d.get_alias(msg.from), + "->>", d.get_alias(msg.to), msg_str); + } + else if (msg.is_response) { + call_pattern = fmt::format("{} {} {} : {}", d.get_alias(msg.from), + "-->>", d.get_alias(msg.to), msg_str); + } + else { + call_pattern = fmt::format("{} {} {} : {}", d.get_alias(msg.from), + "->>", d.get_alias(msg.to), msg_str); + } + + auto match_offset = d.find(call_pattern, offset); + + if (match_offset < 0) { + if (fail) + FAIL(fmt::format("Missing message: {} -> {} {} ({})", + msg.from.str(), msg.to.str(), msg.message, call_pattern)); + return -1; + } + + return match_offset + offset; +} + +template <> +bool HasMessageComment( + const mermaid_t &d, std::string const &participant, std::string const ¬e) +{ + std::string note_escaped{note}; + util::replace_all(note_escaped, "\\n", "
"); + + return d.contains(std::string("note over ") + d.get_alias(participant) + + ": " + note_escaped); +} + +template <> +bool IsParticipant( + const mermaid_t &d, const std::string &name, const std::string &type) +{ + return d.contains(fmt::format("participant {}", d.get_alias(name))); +} + +// +// JSON test helpers +// struct File { explicit File(const std::string &f) : file{f} @@ -1144,168 +1834,472 @@ struct File { const std::string file; }; -std::optional get_element_by_id( - const nlohmann::json &j, const std::string &id) +template <> bool HasTitle(const json_t &d, std::string const &str) { - if (!j.contains("elements")) - return {}; - - for (const nlohmann::json &e : j["elements"]) { - if (e["id"] == id) - return {e}; - - if (e["type"] == "namespace" || e["type"] == "folder") { - auto maybe_e = get_element_by_id(e, id); - if (maybe_e) - return maybe_e; - } - } - - return {}; + return d.src.contains("title") && d.src["title"] == str; } -std::optional get_element( - const nlohmann::json &j, const std::string &name) +template <> bool IsAbstractClass(const json_t &d, QualifiedName cls) { - if (!j.contains("elements")) - return {}; - - for (const nlohmann::json &e : j["elements"]) { - if (e["display_name"] == name) - return {e}; - - if (e["type"] == "namespace" || e["type"] == "folder" || - e["type"] == "directory" || e["type"] == "module") { - auto maybe_e = get_element(e, name); - if (maybe_e) - return maybe_e; - } - } - - return {}; + auto e = + get_element(d.src, expand_name(d.src, cls.str(d.generate_packages))); + return e && e->at("type") == "class" && e->at("is_abstract"); } -std::optional get_participant( - const nlohmann::json &j, const std::string &name) +template <> bool IsEnum(const json_t &d, QualifiedName enm) { - if (!j.contains("participants")) - return {}; - - for (const nlohmann::json &e : j.at("participants")) { - if (e["display_name"] == name) - return {e}; - } - - return {}; -} - -auto get_relationship(const nlohmann::json &j, const nlohmann::json &from, - const nlohmann::json &to, const std::string &type) -{ - return std::find_if(j["relationships"].begin(), j["relationships"].end(), - [&](const auto &it) { - return (it["source"] == from) && (it["destination"] == to) && - (it["type"] == type); - }); -} - -auto get_relationship(const nlohmann::json &j, const std::string &from, - const std::string &to, const std::string &type) -{ - auto source = get_element(j, from); - auto destination = get_element(j, to); - - if (!(source && destination)) - return j["relationships"].end(); - - return get_relationship(j, source->at("id"), destination->at("id"), type); -} - -std::string expand_name(const nlohmann::json &j, const std::string &name) -{ - return name; -} - -bool HasTitle(const nlohmann::json &j, const std::string &title) -{ - return j.contains("title") && j["title"] == title; -} - -bool IsClass(const nlohmann::json &j, const std::string &name) -{ - auto e = get_element(j, expand_name(j, name)); - return e && e->at("type") == "class"; -} - -bool IsStruct(const nlohmann::json &j, const std::string &name) -{ - auto e = get_element(j, expand_name(j, name)); - return e && e->at("type") == "class" && e->at("is_struct"); -} - -bool InPublicModule(const nlohmann::json &j, const std::string &element, - const std::string &module) -{ - auto e = get_element(j, expand_name(j, element)); - return e && e->contains("module") && e->at("module")["name"] == module && - !e->at("module")["is_private"]; -} - -bool InPrivateModule(const nlohmann::json &j, const std::string &element, - const std::string &module) -{ - auto e = get_element(j, expand_name(j, element)); - return e && e->contains("module") && e->at("module")["name"] == module && - e->at("module")["is_private"]; -} - -bool IsAbstractClass(const nlohmann::json &j, const std::string &name) -{ - auto e = get_element(j, expand_name(j, name)); - return e && (e->at("type") == "class") && (e->at("is_abstract") == true); -} - -bool IsClassTemplate(const nlohmann::json &j, const std::string &name) -{ - auto e = get_element(j, expand_name(j, name)); - return e && e->at("type") == "class" && e->at("is_template") == true; -} - -bool IsConcept(const nlohmann::json &j, const std::string &name) -{ - auto e = get_element(j, expand_name(j, name)); - return e && e->at("type") == "concept"; -} - -bool IsEnum(const nlohmann::json &j, const std::string &name) -{ - auto e = get_element(j, expand_name(j, name)); + auto e = + get_element(d.src, expand_name(d.src, enm.str(d.generate_packages))); return e && e->at("type") == "enum"; } -bool IsPackage(const nlohmann::json &j, const std::string &name, - const std::string &type = "namespace") +template <> bool IsUnion(const json_t &d, QualifiedName enm) { - auto e = get_element(j, expand_name(j, name)); - return e && e->at("type") == type; + auto e = + get_element(d.src, expand_name(d.src, enm.str(d.generate_packages))); + return e && e->at("type") == "class" && e->at("is_union"); } -struct NamespacePackage { }; -struct ModulePackage { }; -struct DirectoryPackage { }; - -template std::string package_type_name(); - -template <> std::string package_type_name() +template <> bool IsClass(const json_t &d, QualifiedName cls) { - return "namespace"; + auto e = + get_element(d.src, expand_name(d.src, cls.str(d.generate_packages))); + return e && e->at("type") == "class" && !e->at("is_abstract"); } -template <> std::string package_type_name() { return "module"; } - -template <> std::string package_type_name() +template <> bool IsClassTemplate(const json_t &d, QualifiedName cls) { - return "directory"; + auto e = + get_element(d.src, expand_name(d.src, cls.str(d.generate_packages))); + return e && e->at("type") == "class"; +} + +template <> bool IsAbstractClassTemplate(const json_t &d, QualifiedName cls) +{ + auto e = + get_element(d.src, expand_name(d.src, cls.str(d.generate_packages))); + return e && e->at("type") == "class" && e->at("is_abstract"); +} + +template <> +bool IsBaseClass(const json_t &d, QualifiedName base, QualifiedName subclass) +{ + const auto &j = d.src; + auto base_el = + get_element(j, expand_name(j, base.str(d.generate_packages))); + auto subclass_el = + get_element(j, expand_name(j, subclass.str(d.generate_packages))); + + if (!base_el || !subclass_el) + return false; + + const nlohmann::json &bases = (*subclass_el)["bases"]; + + return std::find_if(bases.begin(), bases.end(), [&](const auto &it) { + return it["id"] == base_el.value()["id"]; + }) != bases.end(); +} + +template <> +bool IsInnerClass( + const json_t &d, std::string const &parent, std::string const &inner) +{ + const auto &j = d.src; + + auto rel = get_relationship( + j, expand_name(j, inner), expand_name(j, parent), "containment"); + + return rel != j["relationships"].end(); +} + +template +bool IsMethod(const json_t &d, const std::string &cls, std::string const &name, + std::string type = "void", std::string const ¶ms = "") +{ + const auto &j = d.src; + auto sc = get_element(j, expand_name(j, cls)); + + if (!sc) + return false; + + const nlohmann::json &methods = (*sc)["methods"]; + + return std::find_if(methods.begin(), methods.end(), [name](const auto &it) { + return it["display_name"] == name; + }) != methods.end(); +} + +template +bool IsField(const json_t &d, QualifiedName cls, std::string const &name, + std::string type) +{ + const auto &j = d.src; + + auto sc = get_element(j, expand_name(j, cls.str(d.generate_packages))); + + if (!sc) + return false; + + const nlohmann::json &members = (*sc)["members"]; + + return std::find_if(members.begin(), members.end(), [&](const auto &it) { + return it["name"] == name && it["type"] == type; + }) != members.end(); +} + +template +bool IsAssociation(const json_t &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = "") +{ + const auto &j = d.src; + + auto rel = get_relationship( + j, expand_name(j, from), expand_name(j, to), "association", label); + + if (rel == j["relationships"].end()) + return false; + + if (!label.empty() && (label != rel->at("label"))) + return false; + + std::string access; + if constexpr (has_type()) + access = "public"; + else if constexpr (has_type()) + access = "protected"; + else + access = "private"; + + if (access != rel->at("access")) + return false; + + return true; +} + +template +bool IsComposition(const json_t &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = "") +{ + const auto &j = d.src; + + auto rel = get_relationship( + j, expand_name(j, from), expand_name(j, to), "composition", label); + + if (rel == j["relationships"].end()) + return false; + + if (!label.empty() && label != rel->at("label")) + return false; + + std::string access; + if constexpr (has_type()) + access = "public"; + else if constexpr (has_type()) + access = "protected"; + else + access = "private"; + + if (access != rel->at("access")) + return false; + + return true; +} + +template +bool IsAggregation(const json_t &d, std::string const &from, + std::string const &to, std::string const &label = "", + std::string multiplicity_source = "", std::string multiplicity_dest = "", + std::string style = "") +{ + const auto &j = d.src; + + auto rel = get_relationship( + j, expand_name(j, from), expand_name(j, to), "aggregation", label); + + if (rel == j["relationships"].end()) + return false; + + if (!label.empty() && label != rel->at("label")) + return false; + + std::string access; + if constexpr (has_type()) + access = "public"; + else if constexpr (has_type()) + access = "protected"; + else + access = "private"; + + if (access != rel->at("access")) + return false; + + return true; +} + +template <> +bool IsInstantiation(const json_t &d, std::string const &from, + std::string const &to, std::string style) +{ + const auto &j = d.src; + + auto rel = get_relationship( + j, expand_name(j, to), expand_name(j, from), "instantiation"); + + if (rel == j["relationships"].end()) + return false; + + return true; +} + +template <> +bool IsDependency( + const json_t &d, QualifiedName from, QualifiedName to, std::string style) +{ + const auto &j = d.src; + + auto rel = + get_relationship(j, expand_name(j, from.str(d.generate_packages)), + expand_name(j, to.str(d.generate_packages)), "dependency"); + + if (rel == j["relationships"].end()) + return false; + + return true; +} + +template +bool IsFriend(const json_t &d, std::string const &from, std::string const &to) +{ + std::string access; + + if constexpr (has_type()) + access = "public"; + else if constexpr (has_type()) + access = "protected"; + else + access = "private"; + + const auto &j = d.src; + + auto rel = get_relationship( + j, expand_name(j, from), expand_name(j, to), "friendship"); + + return rel != j["relationships"].end() && rel->at("access") == access; +} + +template <> +bool IsPackageDependency( + const json_t &d, std::string const &from, std::string const &to) +{ + const auto &j = d.src; + + auto rel = get_relationship( + j, expand_name(j, from), expand_name(j, to), "dependency"); + + if (rel == j["relationships"].end()) + return false; + + return true; +} + +template <> +bool IsIncludeDependency( + const json_t &d, std::string const &from, std::string const &to) +{ + const auto &j = d.src; + + auto rel = get_relationship( + j, expand_name(j, from), expand_name(j, to), "dependency"); + + if (rel == j["relationships"].end()) + return false; + + return true; +} + +template <> bool IsConcept(const json_t &d, QualifiedName cpt) +{ + const auto &j = d.src; + + auto e = get_element(j, expand_name(j, cpt.str(d.generate_packages))); + return e && e->at("type") == "concept"; +} + +template <> +bool IsConstraint(const json_t &d, QualifiedName from, QualifiedName to, + std::string label, std::string style) +{ + const auto &j = d.src; + + auto rel = + get_relationship(j, expand_name(j, from.str(d.generate_packages)), + expand_name(j, to.str(d.generate_packages)), "constraint", label); + + if (rel == j["relationships"].end()) + return false; + + if ((*rel)["label"] != label) + return false; + + return true; +} + +template <> +bool IsConceptRequirement( + const json_t &d, std::string const &cpt, std::string requirement) +{ + const auto &j = d.src; + + auto e = get_element(j, expand_name(j, cpt)); + + if (!e) + return false; + + const nlohmann::json &statements = (*e)["statements"]; + + return std::find_if(statements.begin(), statements.end(), + [requirement](const auto &it) { return it == requirement; }) != + statements.end(); +} + +template <> +bool IsConceptParameterList( + const json_t &d, std::string const &cpt, std::string parameter_list) +{ + const auto &j = d.src; + + auto e = get_element(j, expand_name(j, cpt)); + + if (!e) + return false; + + const nlohmann::json ¶meters = (*e)["parameters"]; + + std::vector params; + for (const auto &it : parameters) { + params.push_back(fmt::format("{} {}", it["type"], it["name"])); + } + + return parameter_list == fmt::format("({})", fmt::join(params, ",")); +} + +template <> +bool IsLayoutHint(const json_t &d, std::string const &from, + std::string const &hint, std::string const &to) +{ + return true; +} + +template <> bool HasComment(const json_t &d, std::string const &comment) +{ + // Comments are not included in JSON + return true; +} + +template <> +bool HasNote(const json_t &d, std::string const &cls, + std::string const &position, std::string const ¬e) +{ + const auto &j = d.src; + + auto sc = get_element(j, expand_name(j, cls)); + + if (!sc) + return false; + + std::string formatted = (*sc)["comment"]["formatted"]; + + return util::contains(formatted, note); +} + +template <> +bool HasPackageNote(const json_t &d, std::string const &cls, + std::string const &position, std::string const ¬e) +{ + return true; +} + +template <> +bool HasMemberNote(const json_t &d, std::string const &cls, + std::string const &member, std::string const &position, + std::string const ¬e) +{ + return true; +} + +template <> +bool HasLink(const json_t &d, std::string const &alias, std::string const &link, + std::string const &tooltip) +{ + return true; +} + +template <> +bool HasMemberLink(const json_t &d, std::string const &method, + std::string const &link, std::string const &tooltip) +{ + return true; +} + +template <> bool IsFolder(const json_t &d, std::string const &path) +{ + const auto &j = d.src; + + auto e = get_element(j, path); + return e && e->at("type") == "folder"; +} + +template <> bool IsFile(const json_t &d, std::string const &path) +{ + const auto &j = d.src; + + auto e = get_element(j, path); + return e && e->at("type") == "file"; +} + +template <> bool IsSystemHeader(const json_t &d, std::string const &path) +{ + const auto &j = d.src; + + auto e = get_element(j, path); + return e && e->at("type") == "file" && e->at("file_kind") == "header" && + e->at("is_system"); +} + +template <> +bool IsHeaderDependency(const json_t &d, std::string const &from, + std::string const &to, std::string style) +{ + assert(d.diagram_type == common::model::diagram_t::kInclude); + const auto &j = d.src; + + auto rel = get_relationship( + j, expand_name(j, from), expand_name(j, to), "association"); + + if (rel == j["relationships"].end()) + return false; + + return true; +} + +template <> +bool IsSystemHeaderDependency(const json_t &d, std::string const &from, + std::string const &to, std::string style) +{ + assert(d.diagram_type == common::model::diagram_t::kInclude); + const auto &j = d.src; + + auto rel = get_relationship( + j, expand_name(j, from), expand_name(j, to), "dependency"); + + if (rel == j["relationships"].end()) + return false; + + return true; } template @@ -1327,230 +2321,49 @@ bool IsPackagePath( } template -bool IsNamespacePackage( - const nlohmann::json &j, const std::string &head, Args... args) +bool IsNamespacePackage(const json_t &d, Args... args) { - return IsPackagePath( - j, head, std::forward(args)...); + const auto &j = d.src; + + return IsPackagePath(j, std::forward(args)...); } template -bool IsDirectoryPackage( - const nlohmann::json &j, const std::string &head, Args... args) +bool IsDirectoryPackage(const json_t &d, Args... args) { - return IsPackagePath( - j, head, std::forward(args)...); + const auto &j = d.src; + + return IsPackagePath(j, std::forward(args)...); } -template -bool IsModulePackage( - const nlohmann::json &j, const std::string &head, Args... args) +template bool IsModulePackage(const json_t &d, Args... args) { - return IsPackagePath(j, head, std::forward(args)...); + const auto &j = d.src; + + return IsPackagePath(j, std::forward(args)...); } -bool IsFolder(const nlohmann::json &j, const std::string &name) +template <> bool IsDeprecated(const json_t &d, const std::string &name) { - auto e = get_element(j, name); - return e && e->at("type") == "folder"; -} + const auto &j = d.src; -bool IsFile(const nlohmann::json &j, const std::string &name) -{ - auto e = get_element(j, name); - return e && e->at("type") == "file"; -} - -bool IsSystemHeader(const nlohmann::json &j, const std::string &name) -{ - auto e = get_element(j, name); - return e && e->at("type") == "file" && e->at("file_kind") == "header" && - e->at("is_system"); -} - -bool IsHeader(const nlohmann::json &j, const std::string &name) -{ - auto e = get_element(j, name); - return e && e->at("type") == "file" && e->at("file_kind") == "header" && - !e->at("is_system"); -} - -bool IsDeprecated(const nlohmann::json &j, const std::string &name) -{ auto e = get_element(j, expand_name(j, name)); return e && e->at("is_deprecated") == true; } -bool IsBaseClass(const nlohmann::json &j, const std::string &base, - const std::string &subclass) -{ - auto base_el = get_element(j, expand_name(j, base)); - auto subclass_el = get_element(j, expand_name(j, subclass)); - - if (!base_el || !subclass_el) - return false; - - const nlohmann::json &bases = (*subclass_el)["bases"]; - - return std::find_if(bases.begin(), bases.end(), [&](const auto &it) { - return it["id"] == base_el.value()["id"]; - }) != bases.end(); -} - -bool IsMethod( - const nlohmann::json &j, const std::string &cls, const std::string &name) -{ - auto sc = get_element(j, expand_name(j, cls)); - - if (!sc) - return false; - - const nlohmann::json &methods = (*sc)["methods"]; - - return std::find_if(methods.begin(), methods.end(), [&](const auto &it) { - return it["name"] == name; - }) != methods.end(); -} - -bool IsField(const nlohmann::json &j, const std::string &cls, - const std::string &name, const std::string &type) -{ - auto sc = get_element(j, expand_name(j, cls)); - - if (!sc) - return false; - - const nlohmann::json &members = (*sc)["members"]; - - return std::find_if(members.begin(), members.end(), [&](const auto &it) { - return it["name"] == name && it["type"] == type; - }) != members.end(); -} - -bool IsAssociation(nlohmann::json j, const std::string &from, - const std::string &to, const std::string &label = "") -{ - auto rel = get_relationship( - j, expand_name(j, from), expand_name(j, to), "association"); - - if (rel == j["relationships"].end()) - return false; - - if (!label.empty() && rel->at("label") != label) - return false; - - return true; -} - -bool IsComposition(nlohmann::json j, const std::string &from, - const std::string &to, const std::string &label = "") -{ - auto rel = get_relationship( - j, expand_name(j, from), expand_name(j, to), "composition"); - - if (rel == j["relationships"].end()) - return false; - - if (!label.empty() && rel->at("label") != label) - return false; - - return true; -} - -bool IsAggregation(nlohmann::json j, const std::string &from, - const std::string &to, const std::string &label = "") -{ - auto rel = get_relationship( - j, expand_name(j, from), expand_name(j, to), "aggregation"); - - if (rel == j["relationships"].end()) - return false; - - if (!label.empty() && rel->at("label") != label) - return false; - - return true; -} - -namespace detail { -bool is_dependency_impl( - nlohmann::json j, const std::string &from, const std::string &to) -{ - auto rel = get_relationship(j, from, to, "dependency"); - - return rel != j["relationships"].end(); -} - -} // namespace detail - -bool IsDependency( - nlohmann::json j, const std::string &from, const std::string &to) -{ - return detail::is_dependency_impl( - j, expand_name(j, from), expand_name(j, to)); -} - -bool IsDependency(nlohmann::json j, const File &from, const File &to) -{ - return detail::is_dependency_impl(j, from.file, to.file); -} - -bool IsInstantiation( - nlohmann::json j, const std::string &from, const std::string &to) -{ - auto rel = get_relationship( - j, expand_name(j, to), expand_name(j, from), "instantiation"); - - return rel != j["relationships"].end(); -} - -bool IsFriend(nlohmann::json j, const std::string &from, const std::string &to) -{ - auto rel = get_relationship( - j, expand_name(j, from), expand_name(j, to), "friendship"); - - return rel != j["relationships"].end(); -} - -bool IsInnerClass( - nlohmann::json j, const std::string &from, const std::string &to) -{ - auto rel = get_relationship( - j, expand_name(j, to), expand_name(j, from), "containment"); - - return rel != j["relationships"].end(); -} - -bool IsParticipant( - const nlohmann::json &j, const std::string &name, const std::string &type) -{ - auto p = get_participant(j, expand_name(j, name)); - - return p && (p->at("type") == type); -} - -bool IsFunctionParticipant(const nlohmann::json &j, const std::string &name) -{ - return IsParticipant(j, name, "function"); -} - -bool IsClassParticipant(const nlohmann::json &j, const std::string &name) -{ - return IsParticipant(j, name, "class"); -} - -bool IsFileParticipant(const nlohmann::json &j, const std::string &name) -{ - return IsParticipant(j, name, "file"); -} - -namespace detail { +namespace json_helpers { int find_message_nested(const nlohmann::json &j, const std::string &from, const std::string &to, const std::string &msg, std::optional return_type, const nlohmann::json &from_p, - const nlohmann::json &to_p, int &count) + const nlohmann::json &to_p, int &count, const int64_t offset, + std::optional chain_index = {}) { - const auto &messages = j["messages"]; + if (!j.contains("messages") && !j.contains("message_chains")) + return -1; + + const auto &messages = !chain_index.has_value() + ? j["messages"] + : j["message_chains"][chain_index.value()]["messages"]; int res{-1}; @@ -1558,21 +2371,22 @@ int find_message_nested(const nlohmann::json &j, const std::string &from, if (m.contains("branches")) { for (const auto &b : m["branches"]) { auto nested_res = find_message_nested( - b, from, to, msg, return_type, from_p, to_p, count); + b, from, to, msg, return_type, from_p, to_p, count, offset); - if (nested_res >= 0) + if (nested_res >= offset) return nested_res; } } else if (m.contains("messages")) { auto nested_res = find_message_nested( - m, from, to, msg, return_type, from_p, to_p, count); + m, from, to, msg, return_type, from_p, to_p, count, offset); - if (nested_res >= 0) + if (nested_res >= offset) return nested_res; } else { - if ((m["from"]["participant_id"] == from_p["id"]) && + if (count >= offset && + (m["from"]["participant_id"] == from_p["id"]) && (m["to"]["participant_id"] == to_p["id"]) && (m["name"] == msg) && (!return_type || m["return_type"] == *return_type)) @@ -1587,106 +2401,173 @@ int find_message_nested(const nlohmann::json &j, const std::string &from, int find_message_impl(const nlohmann::json &j, const std::string &from, const std::string &to, const std::string &msg, - std::optional return_type) + std::optional return_type, int64_t offset, + std::optional chain_index = {}) { auto from_p = get_participant(j, from); auto to_p = get_participant(j, to); - // TODO: support diagrams with multiple sequences... - const auto &sequence_0 = j["sequences"][0]; + if (!from_p) + throw std::runtime_error( + fmt::format("Cannot find participant {}", from)); + if (!to_p) + throw std::runtime_error(fmt::format("Cannot find participant {}", to)); + + assert(from_p->is_object()); + assert(to_p->is_object()); + + // TODO: support diagrams with multiple sequences... int count{0}; - auto res = detail::find_message_nested( - sequence_0, from, to, msg, return_type, *from_p, *to_p, count); + for (const auto &seq : j["sequences"]) { + int64_t res{-1}; - if (res >= 0) - return res; + res = find_message_nested(seq, from, to, msg, return_type, *from_p, + *to_p, count, offset, chain_index); - throw std::runtime_error( - fmt::format("No such message {} {} {}", from, to, msg)); + if (res >= 0) + return res; + } + + throw std::runtime_error(fmt::format( + "No such message {} {} {} after offset {}", from, to, msg, offset)); +} + +int64_t find_message(const nlohmann::json &j, const File &from, const File &to, + const std::string &msg, int64_t offset) +{ + return find_message_impl(j, from.file, to.file, msg, {}, offset); +} + +int64_t find_message(const nlohmann::json &j, const std::string &from, + const std::string &to, const std::string &msg, + std::optional return_type = {}, int64_t offset = 0) +{ + return find_message_impl( + j, expand_name(j, from), expand_name(j, to), msg, return_type, offset); +} + +int64_t find_message_in_chain(const nlohmann::json &j, const std::string &from, + const std::string &to, const std::string &msg, + std::optional return_type = {}, int64_t offset = 0, + uint32_t chain_index = 0) +{ + return find_message_impl(j, expand_name(j, from), expand_name(j, to), msg, + return_type, offset, chain_index); } } // namespace detail -int FindMessage(const nlohmann::json &j, const File &from, const File &to, - const std::string &msg) +template <> +int64_t FindMessage( + const json_t &d, const Message &msg, int64_t offset, bool fail) { - return detail::find_message_impl(j, from.file, to.file, msg, {}); -} - -int FindMessage(const nlohmann::json &j, const std::string &from, - const std::string &to, const std::string &msg, - std::optional return_type = {}) -{ - return detail::find_message_impl( - j, expand_name(j, from), expand_name(j, to), msg, return_type); -} - -struct message_test_spec_t { - std::string from; - std::string to; - std::optional return_type; - - bool operator==(const message_test_spec_t &r) const noexcept - { - return from == r.from && to == r.to && return_type == r.return_type; - } -}; - -void from_json(const nlohmann::json &j, message_test_spec_t &p) -{ - j.at("from").at("activity_id").get_to(p.from); - j.at("to").at("activity_id").get_to(p.to); - j.at("return_type").get_to(p.return_type); -} - -std::string get_activity_id( - const nlohmann::json &j, const std::string &display_name) -{ - for (const auto &p : j["participants"]) { - if (p.contains("activities")) { - for (const auto &a : p["activities"]) { - if (a["display_name"] == display_name) { - return a["id"]; - } - } - } - else if (p["display_name"] == display_name) { - return p["id"]; - } + if (msg.is_response) { + // TODO: Currently response are not generated as separate messages in + // JSON format + return offset; } - return {}; + if (msg.is_entrypoint || msg.is_exitpoint) + return offset; + + try { + return json_helpers::find_message(d.src, msg.from.str(), msg.to.str(), + msg.message, msg.return_type, offset); + } + catch (std::exception &e) { + if (!fail) + return -1; + + std::cout << "FindMessage failed with error " << e.what() << "\n"; + + throw e; + } } -bool HasMessageChain( - const nlohmann::json &j, std::vector msgs) +int64_t find_message_in_chain(const json_t &d, const Message &msg, + int64_t offset, bool fail, uint32_t chain_index) { - std::vector full_name_messages; - std::transform(msgs.begin(), msgs.end(), - std::back_inserter(full_name_messages), - [&j](const message_test_spec_t &m) { - auto res = m; - res.from = get_activity_id(j, m.from); - res.to = get_activity_id(j, m.to); - return res; - }); + if (msg.is_response) { + // TODO: Currently response are not generated as separate messages in + // JSON format + return offset; + } - for (const auto &seq : j.at("sequences")) - for (const auto &mc : seq.at("message_chains")) { - auto mc_msgs = - mc.at("messages").get>(); + if (msg.is_entrypoint || msg.is_exitpoint) + return offset; - if (full_name_messages == mc_msgs) + try { + return json_helpers::find_message_in_chain(d.src, msg.from.str(), + msg.to.str(), msg.message, msg.return_type, offset, chain_index); + } + catch (std::exception &e) { + if (!fail) + return -1; + + std::cout << "find_message_in_chain failed with " << e.what() << "\n"; + + throw e; + } +} + +template <> +bool MessageChainsOrder( + const json_t &d, std::vector> message_chains) +{ + const auto sequence_chains_count{ + d.src["sequences"][0]["message_chains"].size()}; + + for (const auto &messages : message_chains) { + for (uint32_t chain_index = 0; chain_index < sequence_chains_count; + chain_index++) { + int64_t offset{0}; + + std::vector order; + order.reserve(messages.size()); + std::transform(messages.begin(), messages.end(), + std::back_inserter(order), + [&d, &offset, chain_index](const auto &m) -> int64_t { + try { + offset = find_message_in_chain( + d, m, offset, true, chain_index); + return offset; + } + catch (...) { + return 0; + } + }); + + bool are_messages_in_order = + std::is_sorted(order.begin(), order.end()); + + if (are_messages_in_order) return true; } + } + + FAIL(fmt::format("Messages are not in order")); return false; } -} // namespace json -} +template <> +bool HasMessageComment( + const json_t &d, std::string const &alias, std::string const ¬e) +{ + return true; } + +template <> +bool IsParticipant( + const json_t &d, const std::string &name, const std::string &type) +{ + const auto &j = d.src; + + auto p = get_participant(j, expand_name(j, name)); + + return p && (p->at("type") == type); } +} // namespace clanguml::test diff --git a/tests/test_cli_handler.cc b/tests/test_cli_handler.cc index 1eaf8658..22e35b7c 100644 --- a/tests/test_cli_handler.cc +++ b/tests/test_cli_handler.cc @@ -15,12 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define CATCH_CONFIG_MAIN +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "cli/cli_handler.h" #include "version.h" -#include "catch.h" +#include "doctest/doctest.h" #include #include @@ -32,7 +32,7 @@ std::shared_ptr make_sstream_logger(std::ostream &ostr) "clanguml-logger", std::move(oss_sink)); } -TEST_CASE("Test cli handler print_version", "[unit-test]") +TEST_CASE("Test cli handler print_version") { using clanguml::cli::cli_flow_t; using clanguml::cli::cli_handler; @@ -52,7 +52,7 @@ TEST_CASE("Test cli handler print_version", "[unit-test]") "clang-uml {}", clanguml::version::CLANG_UML_VERSION)) == 0); } -TEST_CASE("Test cli handler print_config", "[unit-test]") +TEST_CASE("Test cli handler print_config") { using clanguml::cli::cli_flow_t; using clanguml::cli::cli_handler; @@ -73,7 +73,7 @@ TEST_CASE("Test cli handler print_config", "[unit-test]") REQUIRE(doc["diagrams"]["class_main"]); } -TEST_CASE("Test cli handler print_diagrams_list", "[unit-test]") +TEST_CASE("Test cli handler print_diagrams_list") { using clanguml::cli::cli_flow_t; using clanguml::cli::cli_handler; @@ -97,7 +97,7 @@ TEST_CASE("Test cli handler print_diagrams_list", "[unit-test]") )"); } -TEST_CASE("Test cli handler print_diagram_templates", "[unit-test]") +TEST_CASE("Test cli handler print_diagram_templates") { using clanguml::cli::cli_flow_t; using clanguml::cli::cli_handler; @@ -123,7 +123,7 @@ TEST_CASE("Test cli handler print_diagram_templates", "[unit-test]") )"); } -TEST_CASE("Test cli handler print_diagram_template", "[unit-test]") +TEST_CASE("Test cli handler print_diagram_template") { using clanguml::cli::cli_flow_t; using clanguml::cli::cli_handler; @@ -158,8 +158,7 @@ TEST_CASE("Test cli handler print_diagram_template", "[unit-test]") )"); } -TEST_CASE( - "Test cli handler add_compile_flag and remove_compile_flag", "[unit-test]") +TEST_CASE("Test cli handler add_compile_flag and remove_compile_flag") { using clanguml::cli::cli_flow_t; using clanguml::cli::cli_handler; @@ -185,8 +184,7 @@ TEST_CASE( REQUIRE(contains(cli.config.remove_compile_flags(), "-I/usr/include")); } -TEST_CASE( - "Test cli handler puml config inheritance with render cmd", "[unit-test]") +TEST_CASE("Test cli handler puml config inheritance with render cmd") { using clanguml::cli::cli_flow_t; using clanguml::cli::cli_handler; diff --git a/tests/test_compilation_database.cc b/tests/test_compilation_database.cc index 928dd6bc..f0c6b26f 100644 --- a/tests/test_compilation_database.cc +++ b/tests/test_compilation_database.cc @@ -15,16 +15,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define CATCH_CONFIG_RUNNER -#define CATCH_CONFIG_CONSOLE_WIDTH 512 +#define DOCTEST_CONFIG_IMPLEMENT -#include "catch.h" +#include "doctest/doctest.h" #include "cli/cli_handler.h" #include "common/compilation_database.h" #include "util/util.h" -#include "catch.h" #include #include @@ -35,7 +33,7 @@ std::shared_ptr make_sstream_logger(std::ostream &ostr) "clanguml-logger", std::move(oss_sink)); } -TEST_CASE("Test compilation_database should work", "[unit-test]") +TEST_CASE("Test compilation_database should work") { using clanguml::common::compilation_database; using clanguml::common::compilation_database_ptr; @@ -82,7 +80,7 @@ TEST_CASE("Test compilation_database should work", "[unit-test]") } } -TEST_CASE("Test compilation_database should throw", "[unit-test]") +TEST_CASE("Test compilation_database should throw") { using clanguml::common::compilation_database; using clanguml::common::compilation_database_ptr; @@ -102,30 +100,23 @@ TEST_CASE("Test compilation_database should throw", "[unit-test]") /// int main(int argc, char *argv[]) { - Catch::Session session; - using namespace Catch::clara; + doctest::Context context; - bool debug_log{false}; - auto cli = session.cli() | - Opt(debug_log, "debug_log")["-u"]["--debug-log"]("Enable debug logs"); - - session.cli(cli); - - int returnCode = session.applyCommandLine(argc, argv); - if (returnCode != 0) - return returnCode; + context.applyCommandLine(argc, argv); clanguml::cli::cli_handler clih; std::vector argvv = { "clang-uml", "--config", "./test_config_data/simple.yml"}; - if (debug_log) - argvv.push_back("-vvv"); - else - argvv.push_back("-q"); + argvv.push_back("-q"); clih.handle_options(argvv.size(), argvv.data()); - return session.run(); + int res = context.run(); + + if (context.shouldExit()) + return res; + + return res; } diff --git a/tests/test_config.cc b/tests/test_config.cc index 898f0b20..9fd3195f 100644 --- a/tests/test_config.cc +++ b/tests/test_config.cc @@ -15,15 +15,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define CATCH_CONFIG_RUNNER -#define CATCH_CONFIG_CONSOLE_WIDTH 512 -#include "catch.h" +#define DOCTEST_CONFIG_IMPLEMENT + +#include "doctest/doctest.h" #include "cli/cli_handler.h" #include "config/config.h" #include "util/util.h" -TEST_CASE("Test config simple", "[unit-test]") +TEST_CASE("Test config simple") { using clanguml::common::model::access_t; using clanguml::common::model::relationship_t; @@ -102,7 +102,7 @@ TEST_CASE("Test config simple", "[unit-test]") relationship_t::kAggregation); } -TEST_CASE("Test config inherited", "[unit-test]") +TEST_CASE("Test config inherited") { auto cfg = clanguml::config::load("./test_config_data/inherited.yml"); @@ -132,7 +132,7 @@ TEST_CASE("Test config inherited", "[unit-test]") CHECK(cus.puml().after.at(1) == "This is a common footnote"); } -TEST_CASE("Test config includes", "[unit-test]") +TEST_CASE("Test config includes") { auto cfg = clanguml::config::load("./test_config_data/includes.yml"); @@ -156,7 +156,7 @@ TEST_CASE("Test config includes", "[unit-test]") clanguml::config::method_arguments::none); } -TEST_CASE("Test config layout", "[unit-test]") +TEST_CASE("Test config layout") { using namespace std::string_literals; @@ -242,7 +242,7 @@ TEST_CASE("Test config layout", "[unit-test]") clanguml::common::model::diagram_t::kPackage); } -TEST_CASE("Test config emitters", "[unit-test]") +TEST_CASE("Test config emitters") { auto cfg = clanguml::config::load("./test_config_data/complete.yml"); @@ -268,7 +268,7 @@ TEST_CASE("Test config emitters", "[unit-test]") std::filesystem::remove(tmp_file); } -TEST_CASE("Test config diagram_templates", "[unit-test]") +TEST_CASE("Test config diagram_templates") { auto cfg = clanguml::config::load("./test_config_data/diagram_templates.yml"); @@ -327,7 +327,7 @@ TEST_CASE("Test config diagram_templates", "[unit-test]") clanguml::common::model::diagram_t::kSequence); } -TEST_CASE("Test config sequence inherited", "[unit-test]") +TEST_CASE("Test config sequence inherited") { auto cfg = clanguml::config::load( "./test_config_data/sequence_inheritable_options.yml"); @@ -344,7 +344,7 @@ TEST_CASE("Test config sequence inherited", "[unit-test]") CHECK(def.generate_return_types() == false); } -TEST_CASE("Test config relative paths handling", "[unit-test]") +TEST_CASE("Test config relative paths handling") { auto cfg = clanguml::config::load("./test_config_data/relative_to.yml"); @@ -378,7 +378,7 @@ TEST_CASE("Test config relative paths handling", "[unit-test]") "{}/test_config_data", std::filesystem::current_path().string())); } -TEST_CASE("Test using_module relative to", "[unit-test]") +TEST_CASE("Test using_module relative to") { auto cfg = clanguml::config::load("./test_config_data/using_module.yml"); @@ -403,7 +403,7 @@ TEST_CASE("Test using_module relative to", "[unit-test]") std::string{"modA"}, std::string{"modB"}, std::string{"modC"}}); } -TEST_CASE("Test config full clang uml dump", "[unit-test]") +TEST_CASE("Test config full clang uml dump") { auto cfg = clanguml::config::load("./test_config_data/clang_uml_config.yml"); @@ -411,7 +411,7 @@ TEST_CASE("Test config full clang uml dump", "[unit-test]") CHECK(cfg.diagrams.size() == 32); } -TEST_CASE("Test config type aliases", "[unit-test]") +TEST_CASE("Test config type aliases") { auto cfg = clanguml::config::load("./test_config_data/type_aliases.yml"); @@ -447,30 +447,23 @@ TEST_CASE("Test config type aliases", "[unit-test]") /// int main(int argc, char *argv[]) { - Catch::Session session; - using namespace Catch::clara; + doctest::Context context; - bool debug_log{false}; - auto cli = session.cli() | - Opt(debug_log, "debug_log")["-u"]["--debug-log"]("Enable debug logs"); - - session.cli(cli); - - int returnCode = session.applyCommandLine(argc, argv); - if (returnCode != 0) - return returnCode; + context.applyCommandLine(argc, argv); clanguml::cli::cli_handler clih; std::vector argvv = { "clang-uml", "--config", "./test_config_data/simple.yml"}; - if (debug_log) - argvv.push_back("-vvv"); - else - argvv.push_back("-q"); + argvv.push_back("-q"); clih.handle_options(argvv.size(), argvv.data()); - return session.run(); + int res = context.run(); + + if (context.shouldExit()) + return res; + + return res; } diff --git a/tests/test_decorator_parser.cc b/tests/test_decorator_parser.cc index 2334cf4f..1e65d8b6 100644 --- a/tests/test_decorator_parser.cc +++ b/tests/test_decorator_parser.cc @@ -15,14 +15,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define CATCH_CONFIG_MAIN +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "decorators/decorators.h" - -#include "catch.h" #include "util/util.h" -TEST_CASE("Test decorator parser on regular comment", "[unit-test]") +#include "doctest/doctest.h" + +TEST_CASE("Test decorator parser on regular comment") { std::string comment = R"( \brief This is a comment. @@ -42,7 +42,7 @@ TEST_CASE("Test decorator parser on regular comment", "[unit-test]") CHECK(clanguml::util::trim(comment) == stripped); } -TEST_CASE("Test decorator parser on note", "[unit-test]") +TEST_CASE("Test decorator parser on note") { std::string comment = R"( \brief This is a comment. @@ -99,7 +99,7 @@ TEST_CASE("Test decorator parser on note", "[unit-test]") \param b float a float)"); } -TEST_CASE("Test decorator parser on note with custom tag", "[unit-test]") +TEST_CASE("Test decorator parser on note with custom tag") { std::string comment = R"( \brief This is a comment. @@ -156,7 +156,7 @@ TEST_CASE("Test decorator parser on note with custom tag", "[unit-test]") \param b float a float)"); } -TEST_CASE("Test decorator parser on style", "[unit-test]") +TEST_CASE("Test decorator parser on style") { std::string comment = R"( \uml{style[#green,dashed,thickness=4]} @@ -175,7 +175,7 @@ TEST_CASE("Test decorator parser on style", "[unit-test]") CHECK(stripped.empty()); } -TEST_CASE("Test decorator parser on aggregation", "[unit-test]") +TEST_CASE("Test decorator parser on aggregation") { std::string comment = R"( \uml{aggregation[0..1:0..*]} @@ -194,7 +194,7 @@ TEST_CASE("Test decorator parser on aggregation", "[unit-test]") CHECK(stripped.empty()); } -TEST_CASE("Test decorator parser on skip", "[unit-test]") +TEST_CASE("Test decorator parser on skip") { std::string comment = R"( \uml{skip} @@ -212,7 +212,7 @@ TEST_CASE("Test decorator parser on skip", "[unit-test]") CHECK(stripped.empty()); } -TEST_CASE("Test decorator parser on skiprelationship", "[unit-test]") +TEST_CASE("Test decorator parser on skiprelationship") { std::string comment = R"( \uml{skiprelationship} @@ -230,7 +230,7 @@ TEST_CASE("Test decorator parser on skiprelationship", "[unit-test]") CHECK(stripped.empty()); } -TEST_CASE("Test decorator parser on diagram scope", "[unit-test]") +TEST_CASE("Test decorator parser on diagram scope") { std::string comment = R"( \uml{note:diagram1, diagram2, @@ -259,7 +259,7 @@ TEST_CASE("Test decorator parser on diagram scope", "[unit-test]") CHECK(stripped.empty()); } -TEST_CASE("Test invalid comment - unterminated curly brace", "[unit-test]") +TEST_CASE("Test invalid comment - unterminated curly brace") { std::string comment = R"( Test test test diff --git a/tests/test_filters.cc b/tests/test_filters.cc index 3590d331..0d2e76e5 100644 --- a/tests/test_filters.cc +++ b/tests/test_filters.cc @@ -15,11 +15,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define DOCTEST_CONFIG_IMPLEMENT -#define CATCH_CONFIG_RUNNER -#define CATCH_CONFIG_CONSOLE_WIDTH 512 - -#include "catch.h" +#include "doctest/doctest.h" #include "class_diagram/model/class.h" #include "cli/cli_handler.h" @@ -31,7 +29,7 @@ #include -TEST_CASE("Test diagram paths filter", "[unit-test]") +TEST_CASE("Test diagram paths filter") { using clanguml::common::model::diagram_filter; using clanguml::common::model::source_file; @@ -56,7 +54,7 @@ TEST_CASE("Test diagram paths filter", "[unit-test]") make_path("sequence_diagram/visitor/translation_unit_visitor.h"))); } -TEST_CASE("Test method_types include filter", "[unit-test]") +TEST_CASE("Test method_types include filter") { using clanguml::class_diagram::model::class_method; using clanguml::common::model::access_t; @@ -81,7 +79,7 @@ TEST_CASE("Test method_types include filter", "[unit-test]") CHECK(!filter.should_include(cm)); } -TEST_CASE("Test method_types exclude filter", "[unit-test]") +TEST_CASE("Test method_types exclude filter") { using clanguml::class_diagram::model::class_method; using clanguml::common::model::access_t; @@ -109,7 +107,7 @@ TEST_CASE("Test method_types exclude filter", "[unit-test]") CHECK(!filter.should_include(cm)); } -TEST_CASE("Test namespaces filter", "[unit-test]") +TEST_CASE("Test namespaces filter") { using clanguml::class_diagram::model::class_method; using clanguml::class_diagram::model::class_parent; @@ -173,7 +171,7 @@ TEST_CASE("Test namespaces filter", "[unit-test]") CHECK(!filter.should_include(p)); } -TEST_CASE("Test elements regexp filter", "[unit-test]") +TEST_CASE("Test elements regexp filter") { using clanguml::class_diagram::model::class_method; using clanguml::common::model::access_t; @@ -213,7 +211,7 @@ TEST_CASE("Test elements regexp filter", "[unit-test]") CHECK(filter.should_include(c)); } -TEST_CASE("Test namespaces regexp filter", "[unit-test]") +TEST_CASE("Test namespaces regexp filter") { using clanguml::class_diagram::model::class_method; using clanguml::class_diagram::model::class_parent; @@ -272,7 +270,7 @@ TEST_CASE("Test namespaces regexp filter", "[unit-test]") CHECK(filter.should_include(p)); } -TEST_CASE("Test subclasses regexp filter", "[unit-test]") +TEST_CASE("Test subclasses regexp filter") { using clanguml::class_diagram::model::class_method; using clanguml::class_diagram::model::class_parent; @@ -362,7 +360,7 @@ TEST_CASE("Test subclasses regexp filter", "[unit-test]") CHECK(!filter.should_include(*diagram.find("ns1::ns2::C1"))); } -TEST_CASE("Test parents regexp filter", "[unit-test]") +TEST_CASE("Test parents regexp filter") { using clanguml::class_diagram::model::class_method; using clanguml::class_diagram::model::class_parent; @@ -452,7 +450,7 @@ TEST_CASE("Test parents regexp filter", "[unit-test]") CHECK(!filter.should_include(*diagram.find("ns1::ns2::Common"))); } -TEST_CASE("Test specializations regexp filter", "[unit-test]") +TEST_CASE("Test specializations regexp filter") { using clanguml::class_diagram::model::class_method; using clanguml::class_diagram::model::class_parent; @@ -516,7 +514,7 @@ TEST_CASE("Test specializations regexp filter", "[unit-test]") CHECK(!filter.should_include(*diagram.find("A"))); } -TEST_CASE("Test context regexp filter", "[unit-test]") +TEST_CASE("Test context regexp filter") { using clanguml::class_diagram::model::class_; using clanguml::class_diagram::model::class_method; @@ -605,7 +603,7 @@ TEST_CASE("Test context regexp filter", "[unit-test]") CHECK(!filter.should_include(*diagram.find("C1"))); } -TEST_CASE("Test dependencies regexp filter", "[unit-test]") +TEST_CASE("Test dependencies regexp filter") { using clanguml::class_diagram::model::class_; using clanguml::class_diagram::model::class_method; @@ -689,7 +687,7 @@ TEST_CASE("Test dependencies regexp filter", "[unit-test]") CHECK(!filter.should_include(*diagram.find("C1"))); } -TEST_CASE("Test dependants regexp filter", "[unit-test]") +TEST_CASE("Test dependants regexp filter") { using clanguml::class_diagram::model::class_; using clanguml::class_diagram::model::class_method; @@ -773,7 +771,7 @@ TEST_CASE("Test dependants regexp filter", "[unit-test]") CHECK(!filter.should_include(*diagram.find("C1"))); } -TEST_CASE("Test callee_types filter", "[unit-test]") +TEST_CASE("Test callee_types filter") { using clanguml::common::to_id; using clanguml::common::model::diagram_filter; @@ -829,30 +827,23 @@ TEST_CASE("Test callee_types filter", "[unit-test]") /// int main(int argc, char *argv[]) { - Catch::Session session; - using namespace Catch::clara; + doctest::Context context; - bool debug_log{false}; - auto cli = session.cli() | - Opt(debug_log, "debug_log")["-u"]["--debug-log"]("Enable debug logs"); - - session.cli(cli); - - int returnCode = session.applyCommandLine(argc, argv); - if (returnCode != 0) - return returnCode; + context.applyCommandLine(argc, argv); clanguml::cli::cli_handler clih; std::vector argvv = { "clang-uml", "--config", "./test_config_data/simple.yml"}; - if (debug_log) - argvv.push_back("-vvv"); - else - argvv.push_back("-q"); + argvv.push_back("-q"); clih.handle_options(argvv.size(), argvv.data()); - return session.run(); + int res = context.run(); + + if (context.shouldExit()) + return res; + + return res; } diff --git a/tests/test_model.cc b/tests/test_model.cc index e9fc4cf9..074c64e7 100644 --- a/tests/test_model.cc +++ b/tests/test_model.cc @@ -15,16 +15,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define CATCH_CONFIG_MAIN +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include "catch.h" +#include "doctest/doctest.h" #include "class_diagram/model/class.h" #include "common/model/namespace.h" #include "common/model/package.h" #include "common/model/template_parameter.h" -TEST_CASE("Test namespace_", "[unit-test]") +TEST_CASE("Test namespace_") { using clanguml::common::model::namespace_; @@ -74,7 +74,7 @@ TEST_CASE("Test namespace_", "[unit-test]") CHECK(ns8.relative(name) == "ccc>"); } -TEST_CASE("Test class_::calculate_specialization_match", "[unit-test]") +TEST_CASE("Test class_::calculate_specialization_match") { using clanguml::class_diagram::model::class_; using clanguml::common::model::template_parameter; @@ -116,8 +116,7 @@ TEST_CASE("Test class_::calculate_specialization_match", "[unit-test]") } } -TEST_CASE( - "Test template_parameter::calculate_specialization_match", "[unit-test]") +TEST_CASE("Test template_parameter::calculate_specialization_match") { using clanguml::common::model::template_parameter; @@ -409,7 +408,7 @@ TEST_CASE( } } -TEST_CASE("Test common::model::package full_name", "[unit-test]") +TEST_CASE("Test common::model::package full_name") { using clanguml::common::model::package; using clanguml::common::model::path; diff --git a/tests/test_query_driver_output_extractor.cc b/tests/test_query_driver_output_extractor.cc index ff35ac6f..b08bfa86 100644 --- a/tests/test_query_driver_output_extractor.cc +++ b/tests/test_query_driver_output_extractor.cc @@ -15,13 +15,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define CATCH_CONFIG_MAIN +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN + +#include "doctest/doctest.h" #include "util/query_driver_output_extractor.h" -#include "catch.h" - -TEST_CASE("Test extract system include paths", "[unit-test]") +TEST_CASE("Test extract system include paths") { std::string output = R"(### diff --git a/tests/test_thread_pool_executor.cc b/tests/test_thread_pool_executor.cc index 369b70a6..0285e49d 100644 --- a/tests/test_thread_pool_executor.cc +++ b/tests/test_thread_pool_executor.cc @@ -15,13 +15,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define CATCH_CONFIG_MAIN +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include "catch.h" +#include "doctest/doctest.h" #include "util/thread_pool_executor.h" -TEST_CASE("Test thread_pool_executor", "[unit-test]") +TEST_CASE("Test thread_pool_executor") { using clanguml::util::thread_pool_executor; diff --git a/tests/test_util.cc b/tests/test_util.cc index 0442e4c9..4caa265b 100644 --- a/tests/test_util.cc +++ b/tests/test_util.cc @@ -15,16 +15,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define CATCH_CONFIG_MAIN +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "util/util.h" #include #include -#include "catch.h" +#include "doctest/doctest.h" -TEST_CASE("Test split", "[unit-test]") +TEST_CASE("Test split") { using C = std::vector; using namespace clanguml::util; @@ -45,7 +45,7 @@ TEST_CASE("Test split", "[unit-test]") CHECK(split("std::vector::detail::", "::") == C{"std", "vector", "detail"}); } -TEST_CASE("Test abbreviate", "[unit-test]") +TEST_CASE("Test abbreviate") { using namespace clanguml::util; @@ -55,7 +55,7 @@ TEST_CASE("Test abbreviate", "[unit-test]") CHECK(abbreviate("abcdefg", 5) == "ab..."); } -TEST_CASE("Test starts_with", "[unit-test]") +TEST_CASE("Test starts_with") { using clanguml::util::starts_with; using std::filesystem::path; @@ -73,7 +73,7 @@ TEST_CASE("Test starts_with", "[unit-test]") CHECK_FALSE(starts_with(path{"c/file1.h"}, path{"c/file2.h"})); } -TEST_CASE("Test replace_all", "[unit-test]") +TEST_CASE("Test replace_all") { using namespace clanguml::util; @@ -95,7 +95,7 @@ TEST_CASE("Test replace_all", "[unit-test]") CHECK(text == orig); } -TEST_CASE("Test extract_template_parameter_index", "[unit-test]") +TEST_CASE("Test extract_template_parameter_index") { using namespace clanguml::common; @@ -124,7 +124,7 @@ TEST_CASE("Test extract_template_parameter_index", "[unit-test]") } } -TEST_CASE("Test parse_unexposed_template_params", "[unit-test]") +TEST_CASE("Test parse_unexposed_template_params") { using namespace clanguml::common; @@ -200,7 +200,7 @@ TEST_CASE("Test parse_unexposed_template_params", "[unit-test]") CHECK(declaration_template[2].type().value() == "Tail"); } -TEST_CASE("Test remove_prefix", "[unit-test]") +TEST_CASE("Test remove_prefix") { using namespace clanguml::util; @@ -224,7 +224,7 @@ TEST_CASE("Test remove_prefix", "[unit-test]") CHECK(collection.empty()); } -TEST_CASE("Test path_to_url", "[unit-test]") +TEST_CASE("Test path_to_url") { namespace fs = std::filesystem; using namespace clanguml::util; @@ -258,7 +258,7 @@ TEST_CASE("Test path_to_url", "[unit-test]") #endif } -TEST_CASE("Test ensure_path_is_absolute", "[unit-test]") +TEST_CASE("Test ensure_path_is_absolute") { using namespace clanguml::util; @@ -278,7 +278,7 @@ TEST_CASE("Test ensure_path_is_absolute", "[unit-test]") path{"/"}.make_preferred()); } -TEST_CASE("Test hash_seed", "[unit-test]") +TEST_CASE("Test hash_seed") { using namespace clanguml::util; @@ -287,7 +287,7 @@ TEST_CASE("Test hash_seed", "[unit-test]") CHECK(hash_seed(1) != hash_seed(2)); } -TEST_CASE("Test tokenize_unexposed_template_parameter", "[unit-test]") +TEST_CASE("Test tokenize_unexposed_template_parameter") { using namespace clanguml::common; @@ -398,7 +398,7 @@ TEST_CASE("Test tokenize_unexposed_template_parameter", "[unit-test]") } } -TEST_CASE("Test format_message_comment", "[unit-test]") +TEST_CASE("Test format_message_comment") { using namespace clanguml::util; @@ -419,7 +419,7 @@ TEST_CASE("Test format_message_comment", "[unit-test]") 15) == "This is a url:\nhttp://example.com/test/12345"); } -TEST_CASE("Test is_relative_to", "[unit-test]") +TEST_CASE("Test is_relative_to") { using std::filesystem::path; using namespace clanguml::util; @@ -432,7 +432,7 @@ TEST_CASE("Test is_relative_to", "[unit-test]") CHECK_FALSE(is_relative_to(child, base2)); } -TEST_CASE("Test parse_source_location", "[unit-test]") +TEST_CASE("Test parse_source_location") { using namespace clanguml::common; diff --git a/thirdparty/doctest/LICENSE.txt b/thirdparty/doctest/LICENSE.txt new file mode 100644 index 00000000..5ae0eb10 --- /dev/null +++ b/thirdparty/doctest/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016-2023 Viktor Kirilov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/thirdparty/doctest/doctest.h b/thirdparty/doctest/doctest.h new file mode 100644 index 00000000..5c754cde --- /dev/null +++ b/thirdparty/doctest/doctest.h @@ -0,0 +1,7106 @@ +// ====================================================================== lgtm [cpp/missing-header-guard] +// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! == +// ====================================================================== +// +// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD +// +// Copyright (c) 2016-2023 Viktor Kirilov +// +// Distributed under the MIT Software License +// See accompanying file LICENSE.txt or copy at +// https://opensource.org/licenses/MIT +// +// The documentation can be found at the library's page: +// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md +// +// ================================================================================================= +// ================================================================================================= +// ================================================================================================= +// +// The library is heavily influenced by Catch - https://github.com/catchorg/Catch2 +// which uses the Boost Software License - Version 1.0 +// see here - https://github.com/catchorg/Catch2/blob/master/LICENSE.txt +// +// The concept of subcases (sections in Catch) and expression decomposition are from there. +// Some parts of the code are taken directly: +// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<> +// - the Approx() helper class for floating point comparison +// - colors in the console +// - breaking into a debugger +// - signal / SEH handling +// - timer +// - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA copy/paste) +// +// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest +// which uses the Boost Software License - Version 1.0 +// see here - https://github.com/martinmoene/lest/blob/master/LICENSE.txt +// +// ================================================================================================= +// ================================================================================================= +// ================================================================================================= + +#ifndef DOCTEST_LIBRARY_INCLUDED +#define DOCTEST_LIBRARY_INCLUDED + +// ================================================================================================= +// == VERSION ====================================================================================== +// ================================================================================================= + +#define DOCTEST_VERSION_MAJOR 2 +#define DOCTEST_VERSION_MINOR 4 +#define DOCTEST_VERSION_PATCH 11 + +// util we need here +#define DOCTEST_TOSTR_IMPL(x) #x +#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) + +#define DOCTEST_VERSION_STR \ + DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \ + DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \ + DOCTEST_TOSTR(DOCTEST_VERSION_PATCH) + +#define DOCTEST_VERSION \ + (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) + +// ================================================================================================= +// == COMPILER VERSION ============================================================================= +// ================================================================================================= + +// ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect + +#ifdef _MSC_VER +#define DOCTEST_CPLUSPLUS _MSVC_LANG +#else +#define DOCTEST_CPLUSPLUS __cplusplus +#endif + +#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH)) + +// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl... +#if defined(_MSC_VER) && defined(_MSC_FULL_VER) +#if _MSC_VER == _MSC_FULL_VER / 10000 +#define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000) +#else // MSVC +#define DOCTEST_MSVC \ + DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000) +#endif // MSVC +#endif // MSVC +#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +#define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__) +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \ + !defined(__INTEL_COMPILER) +#define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#endif // GCC +#if defined(__INTEL_COMPILER) +#define DOCTEST_ICC DOCTEST_COMPILER(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif // ICC + +#ifndef DOCTEST_MSVC +#define DOCTEST_MSVC 0 +#endif // DOCTEST_MSVC +#ifndef DOCTEST_CLANG +#define DOCTEST_CLANG 0 +#endif // DOCTEST_CLANG +#ifndef DOCTEST_GCC +#define DOCTEST_GCC 0 +#endif // DOCTEST_GCC +#ifndef DOCTEST_ICC +#define DOCTEST_ICC 0 +#endif // DOCTEST_ICC + +// ================================================================================================= +// == COMPILER WARNINGS HELPERS ==================================================================== +// ================================================================================================= + +#if DOCTEST_CLANG && !DOCTEST_ICC +#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) +#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push") +#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w) +#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop") +#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \ + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w) +#else // DOCTEST_CLANG +#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +#define DOCTEST_CLANG_SUPPRESS_WARNING(w) +#define DOCTEST_CLANG_SUPPRESS_WARNING_POP +#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) +#endif // DOCTEST_CLANG + +#if DOCTEST_GCC +#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) +#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push") +#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w) +#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop") +#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \ + DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w) +#else // DOCTEST_GCC +#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH +#define DOCTEST_GCC_SUPPRESS_WARNING(w) +#define DOCTEST_GCC_SUPPRESS_WARNING_POP +#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) +#endif // DOCTEST_GCC + +#if DOCTEST_MSVC +#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push)) +#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w)) +#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop)) +#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w) +#else // DOCTEST_MSVC +#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH +#define DOCTEST_MSVC_SUPPRESS_WARNING(w) +#define DOCTEST_MSVC_SUPPRESS_WARNING_POP +#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) +#endif // DOCTEST_MSVC + +// ================================================================================================= +// == COMPILER WARNINGS ============================================================================ +// ================================================================================================= + +// both the header and the implementation suppress all of these, +// so it only makes sense to aggregate them like so +#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \ + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \ + \ + DOCTEST_GCC_SUPPRESS_WARNING_PUSH \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \ + \ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + /* these 4 also disabled globally via cmake: */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \ + /* common ones */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \ + /* static analysis */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */ + +#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH + +DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated") + +DOCTEST_GCC_SUPPRESS_WARNING_PUSH +DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy") +DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor") +DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo") + +DOCTEST_MSVC_SUPPRESS_WARNING_PUSH +DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted + +#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */ + +#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP + +// ================================================================================================= +// == FEATURE DETECTION ============================================================================ +// ================================================================================================= + +// general compiler feature support table: https://en.cppreference.com/w/cpp/compiler_support +// MSVC C++11 feature support table: https://msdn.microsoft.com/en-us/library/hh567368.aspx +// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html +// MSVC version table: +// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering +// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022) +// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) +// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017) +// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) +// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) +// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) +// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) +// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) +// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) + +// Universal Windows Platform support +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define DOCTEST_CONFIG_NO_WINDOWS_SEH +#endif // WINAPI_FAMILY +#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH) +#define DOCTEST_CONFIG_WINDOWS_SEH +#endif // MSVC +#if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && defined(DOCTEST_CONFIG_WINDOWS_SEH) +#undef DOCTEST_CONFIG_WINDOWS_SEH +#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH + +#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \ + !defined(__EMSCRIPTEN__) && !defined(__wasi__) +#define DOCTEST_CONFIG_POSIX_SIGNALS +#endif // _WIN32 +#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS) +#undef DOCTEST_CONFIG_POSIX_SIGNALS +#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS +#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \ + || defined(__wasi__) +#define DOCTEST_CONFIG_NO_EXCEPTIONS +#endif // no exceptions +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS +#define DOCTEST_CONFIG_NO_EXCEPTIONS +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS + +#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS) +#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS + +#ifdef __wasi__ +#define DOCTEST_CONFIG_NO_MULTITHREADING +#endif + +#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT) +#define DOCTEST_CONFIG_IMPLEMENT +#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN + +#if defined(_WIN32) || defined(__CYGWIN__) +#if DOCTEST_MSVC +#define DOCTEST_SYMBOL_EXPORT __declspec(dllexport) +#define DOCTEST_SYMBOL_IMPORT __declspec(dllimport) +#else // MSVC +#define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport)) +#define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport)) +#endif // MSVC +#else // _WIN32 +#define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default"))) +#define DOCTEST_SYMBOL_IMPORT +#endif // _WIN32 + +#ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL +#ifdef DOCTEST_CONFIG_IMPLEMENT +#define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT +#else // DOCTEST_CONFIG_IMPLEMENT +#define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT +#endif // DOCTEST_CONFIG_IMPLEMENT +#else // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL +#define DOCTEST_INTERFACE +#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL + +// needed for extern template instantiations +// see https://github.com/fmtlib/fmt/issues/2228 +#if DOCTEST_MSVC +#define DOCTEST_INTERFACE_DECL +#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE +#else // DOCTEST_MSVC +#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE +#define DOCTEST_INTERFACE_DEF +#endif // DOCTEST_MSVC + +#define DOCTEST_EMPTY + +#if DOCTEST_MSVC +#define DOCTEST_NOINLINE __declspec(noinline) +#define DOCTEST_UNUSED +#define DOCTEST_ALIGNMENT(x) +#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0) +#define DOCTEST_NOINLINE +#define DOCTEST_UNUSED +#define DOCTEST_ALIGNMENT(x) +#else +#define DOCTEST_NOINLINE __attribute__((noinline)) +#define DOCTEST_UNUSED __attribute__((unused)) +#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) +#endif + +#ifdef DOCTEST_CONFIG_NO_CONTRADICTING_INLINE +#define DOCTEST_INLINE_NOINLINE inline +#else +#define DOCTEST_INLINE_NOINLINE inline DOCTEST_NOINLINE +#endif + +#ifndef DOCTEST_NORETURN +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_NORETURN +#else // DOCTEST_MSVC +#define DOCTEST_NORETURN [[noreturn]] +#endif // DOCTEST_MSVC +#endif // DOCTEST_NORETURN + +#ifndef DOCTEST_NOEXCEPT +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_NOEXCEPT +#else // DOCTEST_MSVC +#define DOCTEST_NOEXCEPT noexcept +#endif // DOCTEST_MSVC +#endif // DOCTEST_NOEXCEPT + +#ifndef DOCTEST_CONSTEXPR +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_CONSTEXPR const +#define DOCTEST_CONSTEXPR_FUNC inline +#else // DOCTEST_MSVC +#define DOCTEST_CONSTEXPR constexpr +#define DOCTEST_CONSTEXPR_FUNC constexpr +#endif // DOCTEST_MSVC +#endif // DOCTEST_CONSTEXPR + +#ifndef DOCTEST_NO_SANITIZE_INTEGER +#if DOCTEST_CLANG >= DOCTEST_COMPILER(3, 7, 0) +#define DOCTEST_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer"))) +#else +#define DOCTEST_NO_SANITIZE_INTEGER +#endif +#endif // DOCTEST_NO_SANITIZE_INTEGER + +// ================================================================================================= +// == FEATURE DETECTION END ======================================================================== +// ================================================================================================= + +#define DOCTEST_DECLARE_INTERFACE(name) \ + virtual ~name(); \ + name() = default; \ + name(const name&) = delete; \ + name(name&&) = delete; \ + name& operator=(const name&) = delete; \ + name& operator=(name&&) = delete; + +#define DOCTEST_DEFINE_INTERFACE(name) \ + name::~name() = default; + +// internal macros for string concatenation and anonymous variable name generation +#define DOCTEST_CAT_IMPL(s1, s2) s1##s2 +#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2) +#ifdef __COUNTER__ // not standard and may be missing for some compilers +#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__) +#else // __COUNTER__ +#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__) +#endif // __COUNTER__ + +#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE +#define DOCTEST_REF_WRAP(x) x& +#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE +#define DOCTEST_REF_WRAP(x) x +#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE + +// not using __APPLE__ because... this is how Catch does it +#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED +#define DOCTEST_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define DOCTEST_PLATFORM_IPHONE +#elif defined(_WIN32) +#define DOCTEST_PLATFORM_WINDOWS +#elif defined(__wasi__) +#define DOCTEST_PLATFORM_WASI +#else // DOCTEST_PLATFORM +#define DOCTEST_PLATFORM_LINUX +#endif // DOCTEST_PLATFORM + +namespace doctest { namespace detail { + static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; } +}} + +#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ + static const int var = doctest::detail::consume(&var, __VA_ARGS__); \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP + +#ifndef DOCTEST_BREAK_INTO_DEBUGGER +// should probably take a look at https://github.com/scottt/debugbreak +#ifdef DOCTEST_PLATFORM_LINUX +#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) +// Break at the location of the failing check if possible +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) +#else +#include +#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP) +#endif +#elif defined(DOCTEST_PLATFORM_MAC) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386) +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) +#elif defined(__ppc__) || defined(__ppc64__) +// https://www.cocoawithlove.com/2008/03/break-into-debugger.html +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler) +#else +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler) +#endif +#elif DOCTEST_MSVC +#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() +#elif defined(__MINGW32__) +DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls") +extern "C" __declspec(dllimport) void __stdcall DebugBreak(); +DOCTEST_GCC_SUPPRESS_WARNING_POP +#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak() +#else // linux +#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast(0)) +#endif // linux +#endif // DOCTEST_BREAK_INTO_DEBUGGER + +// this is kept here for backwards compatibility since the config option was changed +#ifdef DOCTEST_CONFIG_USE_IOSFWD +#ifndef DOCTEST_CONFIG_USE_STD_HEADERS +#define DOCTEST_CONFIG_USE_STD_HEADERS +#endif +#endif // DOCTEST_CONFIG_USE_IOSFWD + +// for clang - always include ciso646 (which drags some std stuff) because +// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in +// which case we don't want to forward declare stuff from std - for reference: +// https://github.com/doctest/doctest/issues/126 +// https://github.com/doctest/doctest/issues/356 +#if DOCTEST_CLANG +#include +#endif // clang + +#ifdef _LIBCPP_VERSION +#ifndef DOCTEST_CONFIG_USE_STD_HEADERS +#define DOCTEST_CONFIG_USE_STD_HEADERS +#endif +#endif // _LIBCPP_VERSION + +#ifdef DOCTEST_CONFIG_USE_STD_HEADERS +#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN +#include +#include +#include +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END +#else // DOCTEST_CONFIG_USE_STD_HEADERS + +// Forward declaring 'X' in namespace std is not permitted by the C++ Standard. +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643) + +namespace std { // NOLINT(cert-dcl58-cpp) +typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using) +typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using) +template +struct char_traits; +template <> +struct char_traits; +template +class basic_ostream; // NOLINT(fuchsia-virtual-inheritance) +typedef basic_ostream> ostream; // NOLINT(modernize-use-using) +template +// NOLINTNEXTLINE +basic_ostream& operator<<(basic_ostream&, const char*); +template +class basic_istream; +typedef basic_istream> istream; // NOLINT(modernize-use-using) +template +class tuple; +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) +// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 +template +class allocator; +template +class basic_string; +using string = basic_string, allocator>; +#endif // VS 2019 +} // namespace std + +DOCTEST_MSVC_SUPPRESS_WARNING_POP + +#endif // DOCTEST_CONFIG_USE_STD_HEADERS + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#include +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + +namespace doctest { + +using std::size_t; + +DOCTEST_INTERFACE extern bool is_running_in_test; + +#ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE +#define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned +#endif + +// A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length +// of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for: +// - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128) +// - if small - capacity left before going on the heap - using the lowest 5 bits +// - if small - 2 bits are left unused - the second and third highest ones +// - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator) +// and the "is small" bit remains "0" ("as well as the capacity left") so its OK +// Idea taken from this lecture about the string implementation of facebook/folly - fbstring +// https://www.youtube.com/watch?v=kPR8h4-qZdk +// TODO: +// - optimizations - like not deleting memory unnecessarily in operator= and etc. +// - resize/reserve/clear +// - replace +// - back/front +// - iterator stuff +// - find & friends +// - push_back/pop_back +// - assign/insert/erase +// - relational operators as free functions - taking const char* as one of the params +class DOCTEST_INTERFACE String +{ +public: + using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE; + +private: + static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members + static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members + + struct view // len should be more than sizeof(view) - because of the final byte for flags + { + char* ptr; + size_type size; + size_type capacity; + }; + + union + { + char buf[len]; // NOLINT(*-avoid-c-arrays) + view data; + }; + + char* allocate(size_type sz); + + bool isOnStack() const noexcept { return (buf[last] & 128) == 0; } + void setOnHeap() noexcept; + void setLast(size_type in = last) noexcept; + void setSize(size_type sz) noexcept; + + void copy(const String& other); + +public: + static DOCTEST_CONSTEXPR size_type npos = static_cast(-1); + + String() noexcept; + ~String(); + + // cppcheck-suppress noExplicitConstructor + String(const char* in); + String(const char* in, size_type in_size); + + String(std::istream& in, size_type in_size); + + String(const String& other); + String& operator=(const String& other); + + String& operator+=(const String& other); + + String(String&& other) noexcept; + String& operator=(String&& other) noexcept; + + char operator[](size_type i) const; + char& operator[](size_type i); + + // the only functions I'm willing to leave in the interface - available for inlining + const char* c_str() const { return const_cast(this)->c_str(); } // NOLINT + char* c_str() { + if (isOnStack()) { + return reinterpret_cast(buf); + } + return data.ptr; + } + + size_type size() const; + size_type capacity() const; + + String substr(size_type pos, size_type cnt = npos) &&; + String substr(size_type pos, size_type cnt = npos) const &; + + size_type find(char ch, size_type pos = 0) const; + size_type rfind(char ch, size_type pos = npos) const; + + int compare(const char* other, bool no_case = false) const; + int compare(const String& other, bool no_case = false) const; + +friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in); +}; + +DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs); + +DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs); + +class DOCTEST_INTERFACE Contains { +public: + explicit Contains(const String& string); + + bool checkWith(const String& other) const; + + String string; +}; + +DOCTEST_INTERFACE String toString(const Contains& in); + +DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs); +DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs); +DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs); + +namespace Color { + enum Enum + { + None = 0, + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White + }; + + DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code); +} // namespace Color + +namespace assertType { + enum Enum + { + // macro traits + + is_warn = 1, + is_check = 2 * is_warn, + is_require = 2 * is_check, + + is_normal = 2 * is_require, + is_throws = 2 * is_normal, + is_throws_as = 2 * is_throws, + is_throws_with = 2 * is_throws_as, + is_nothrow = 2 * is_throws_with, + + is_false = 2 * is_nothrow, + is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types + + is_eq = 2 * is_unary, + is_ne = 2 * is_eq, + + is_lt = 2 * is_ne, + is_gt = 2 * is_lt, + + is_ge = 2 * is_gt, + is_le = 2 * is_ge, + + // macro types + + DT_WARN = is_normal | is_warn, + DT_CHECK = is_normal | is_check, + DT_REQUIRE = is_normal | is_require, + + DT_WARN_FALSE = is_normal | is_false | is_warn, + DT_CHECK_FALSE = is_normal | is_false | is_check, + DT_REQUIRE_FALSE = is_normal | is_false | is_require, + + DT_WARN_THROWS = is_throws | is_warn, + DT_CHECK_THROWS = is_throws | is_check, + DT_REQUIRE_THROWS = is_throws | is_require, + + DT_WARN_THROWS_AS = is_throws_as | is_warn, + DT_CHECK_THROWS_AS = is_throws_as | is_check, + DT_REQUIRE_THROWS_AS = is_throws_as | is_require, + + DT_WARN_THROWS_WITH = is_throws_with | is_warn, + DT_CHECK_THROWS_WITH = is_throws_with | is_check, + DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, + + DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, + DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, + DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, + + DT_WARN_NOTHROW = is_nothrow | is_warn, + DT_CHECK_NOTHROW = is_nothrow | is_check, + DT_REQUIRE_NOTHROW = is_nothrow | is_require, + + DT_WARN_EQ = is_normal | is_eq | is_warn, + DT_CHECK_EQ = is_normal | is_eq | is_check, + DT_REQUIRE_EQ = is_normal | is_eq | is_require, + + DT_WARN_NE = is_normal | is_ne | is_warn, + DT_CHECK_NE = is_normal | is_ne | is_check, + DT_REQUIRE_NE = is_normal | is_ne | is_require, + + DT_WARN_GT = is_normal | is_gt | is_warn, + DT_CHECK_GT = is_normal | is_gt | is_check, + DT_REQUIRE_GT = is_normal | is_gt | is_require, + + DT_WARN_LT = is_normal | is_lt | is_warn, + DT_CHECK_LT = is_normal | is_lt | is_check, + DT_REQUIRE_LT = is_normal | is_lt | is_require, + + DT_WARN_GE = is_normal | is_ge | is_warn, + DT_CHECK_GE = is_normal | is_ge | is_check, + DT_REQUIRE_GE = is_normal | is_ge | is_require, + + DT_WARN_LE = is_normal | is_le | is_warn, + DT_CHECK_LE = is_normal | is_le | is_check, + DT_REQUIRE_LE = is_normal | is_le | is_require, + + DT_WARN_UNARY = is_normal | is_unary | is_warn, + DT_CHECK_UNARY = is_normal | is_unary | is_check, + DT_REQUIRE_UNARY = is_normal | is_unary | is_require, + + DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, + DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, + DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, + }; +} // namespace assertType + +DOCTEST_INTERFACE const char* assertString(assertType::Enum at); +DOCTEST_INTERFACE const char* failureString(assertType::Enum at); +DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file); + +struct DOCTEST_INTERFACE TestCaseData +{ + String m_file; // the file in which the test was registered (using String - see #350) + unsigned m_line; // the line where the test was registered + const char* m_name; // name of the test case + const char* m_test_suite; // the test suite in which the test was added + const char* m_description; + bool m_skip; + bool m_no_breaks; + bool m_no_output; + bool m_may_fail; + bool m_should_fail; + int m_expected_failures; + double m_timeout; +}; + +struct DOCTEST_INTERFACE AssertData +{ + // common - for all asserts + const TestCaseData* m_test_case; + assertType::Enum m_at; + const char* m_file; + int m_line; + const char* m_expr; + bool m_failed; + + // exception-related - for all asserts + bool m_threw; + String m_exception; + + // for normal asserts + String m_decomp; + + // for specific exception-related asserts + bool m_threw_as; + const char* m_exception_type; + + class DOCTEST_INTERFACE StringContains { + private: + Contains content; + bool isContains; + + public: + StringContains(const String& str) : content(str), isContains(false) { } + StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) { } + + bool check(const String& str) { return isContains ? (content == str) : (content.string == str); } + + operator const String&() const { return content.string; } + + const char* c_str() const { return content.string.c_str(); } + } m_exception_string; + + AssertData(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const StringContains& exception_string); +}; + +struct DOCTEST_INTERFACE MessageData +{ + String m_string; + const char* m_file; + int m_line; + assertType::Enum m_severity; +}; + +struct DOCTEST_INTERFACE SubcaseSignature +{ + String m_name; + const char* m_file; + int m_line; + + bool operator==(const SubcaseSignature& other) const; + bool operator<(const SubcaseSignature& other) const; +}; + +struct DOCTEST_INTERFACE IContextScope +{ + DOCTEST_DECLARE_INTERFACE(IContextScope) + virtual void stringify(std::ostream*) const = 0; +}; + +namespace detail { + struct DOCTEST_INTERFACE TestCase; +} // namespace detail + +struct ContextOptions //!OCLINT too many fields +{ + std::ostream* cout = nullptr; // stdout stream + String binary_name; // the test binary name + + const detail::TestCase* currentTest = nullptr; + + // == parameters from the command line + String out; // output filename + String order_by; // how tests should be ordered + unsigned rand_seed; // the seed for rand ordering + + unsigned first; // the first (matching) test to be executed + unsigned last; // the last (matching) test to be executed + + int abort_after; // stop tests after this many failed assertions + int subcase_filter_levels; // apply the subcase filters for the first N levels + + bool success; // include successful assertions in output + bool case_sensitive; // if filtering should be case sensitive + bool exit; // if the program should be exited after the tests are ran/whatever + bool duration; // print the time duration of each test case + bool minimal; // minimal console output (only test failures) + bool quiet; // no console output + bool no_throw; // to skip exceptions-related assertion macros + bool no_exitcode; // if the framework should return 0 as the exitcode + bool no_run; // to not run the tests at all (can be done with an "*" exclude) + bool no_intro; // to not print the intro of the framework + bool no_version; // to not print the version of the framework + bool no_colors; // if output to the console should be colorized + bool force_colors; // forces the use of colors even when a tty cannot be detected + bool no_breaks; // to not break into the debugger + bool no_skip; // don't skip test cases which are marked to be skipped + bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x): + bool no_path_in_filenames; // if the path to files should be removed from the output + bool no_line_numbers; // if source code line numbers should be omitted from the output + bool no_debug_output; // no output in the debug console when a debugger is attached + bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!! + bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!! + + bool help; // to print the help + bool version; // to print the version + bool count; // if only the count of matching tests is to be retrieved + bool list_test_cases; // to list all tests matching the filters + bool list_test_suites; // to list all suites matching the filters + bool list_reporters; // lists all registered reporters +}; + +namespace detail { + namespace types { +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + using namespace std; +#else + template + struct enable_if { }; + + template + struct enable_if { using type = T; }; + + struct true_type { static DOCTEST_CONSTEXPR bool value = true; }; + struct false_type { static DOCTEST_CONSTEXPR bool value = false; }; + + template struct remove_reference { using type = T; }; + template struct remove_reference { using type = T; }; + template struct remove_reference { using type = T; }; + + template struct is_rvalue_reference : false_type { }; + template struct is_rvalue_reference : true_type { }; + + template struct remove_const { using type = T; }; + template struct remove_const { using type = T; }; + + // Compiler intrinsics + template struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); }; + template struct underlying_type { using type = __underlying_type(T); }; + + template struct is_pointer : false_type { }; + template struct is_pointer : true_type { }; + + template struct is_array : false_type { }; + // NOLINTNEXTLINE(*-avoid-c-arrays) + template struct is_array : true_type { }; +#endif + } + + // + template + T&& declval(); + + template + DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type& t) DOCTEST_NOEXCEPT { + return static_cast(t); + } + + template + DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type&& t) DOCTEST_NOEXCEPT { + return static_cast(t); + } + + template + struct deferred_false : types::false_type { }; + +// MSVS 2015 :( +#if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900 + template + struct has_global_insertion_operator : types::false_type { }; + + template + struct has_global_insertion_operator(), declval()), void())> : types::true_type { }; + + template + struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; }; + + template + struct insert_hack; + + template + struct insert_hack { + static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); } + }; + + template + struct insert_hack { + static void insert(std::ostream& os, const T& t) { operator<<(os, t); } + }; + + template + using insert_hack_t = insert_hack::value>; +#else + template + struct has_insertion_operator : types::false_type { }; +#endif + + template + struct has_insertion_operator(), declval()), void())> : types::true_type { }; + + template + struct should_stringify_as_underlying_type { + static DOCTEST_CONSTEXPR bool value = detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value; + }; + + DOCTEST_INTERFACE std::ostream* tlssPush(); + DOCTEST_INTERFACE String tlssPop(); + + template + struct StringMakerBase { + template + static String convert(const DOCTEST_REF_WRAP(T)) { +#ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES + static_assert(deferred_false::value, "No stringification detected for type T. See string conversion manual"); +#endif + return "{?}"; + } + }; + + template + struct filldata; + + template + void filloss(std::ostream* stream, const T& in) { + filldata::fill(stream, in); + } + + template + void filloss(std::ostream* stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays) + // T[N], T(&)[N], T(&&)[N] have same behaviour. + // Hence remove reference. + filloss::type>(stream, in); + } + + template + String toStream(const T& in) { + std::ostream* stream = tlssPush(); + filloss(stream, in); + return tlssPop(); + } + + template <> + struct StringMakerBase { + template + static String convert(const DOCTEST_REF_WRAP(T) in) { + return toStream(in); + } + }; +} // namespace detail + +template +struct StringMaker : public detail::StringMakerBase< + detail::has_insertion_operator::value || detail::types::is_pointer::value || detail::types::is_array::value> +{}; + +#ifndef DOCTEST_STRINGIFY +#ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY +#define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__)) +#else +#define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__) +#endif +#endif + +template +String toString() { +#if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0 + String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void) + String::size_type beginPos = ret.find('<'); + return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast(sizeof(">(void)"))); +#else + String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] + String::size_type begin = ret.find('=') + 2; + return ret.substr(begin, ret.size() - begin - 1); +#endif +} + +template ::value, bool>::type = true> +String toString(const DOCTEST_REF_WRAP(T) value) { + return StringMaker::convert(value); +} + +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +DOCTEST_INTERFACE String toString(const char* in); +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) +// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 +DOCTEST_INTERFACE String toString(const std::string& in); +#endif // VS 2019 + +DOCTEST_INTERFACE String toString(String in); + +DOCTEST_INTERFACE String toString(std::nullptr_t); + +DOCTEST_INTERFACE String toString(bool in); + +DOCTEST_INTERFACE String toString(float in); +DOCTEST_INTERFACE String toString(double in); +DOCTEST_INTERFACE String toString(double long in); + +DOCTEST_INTERFACE String toString(char in); +DOCTEST_INTERFACE String toString(char signed in); +DOCTEST_INTERFACE String toString(char unsigned in); +DOCTEST_INTERFACE String toString(short in); +DOCTEST_INTERFACE String toString(short unsigned in); +DOCTEST_INTERFACE String toString(signed in); +DOCTEST_INTERFACE String toString(unsigned in); +DOCTEST_INTERFACE String toString(long in); +DOCTEST_INTERFACE String toString(long unsigned in); +DOCTEST_INTERFACE String toString(long long in); +DOCTEST_INTERFACE String toString(long long unsigned in); + +template ::value, bool>::type = true> +String toString(const DOCTEST_REF_WRAP(T) value) { + using UT = typename detail::types::underlying_type::type; + return (DOCTEST_STRINGIFY(static_cast(value))); +} + +namespace detail { + template + struct filldata + { + static void fill(std::ostream* stream, const T& in) { +#if defined(_MSC_VER) && _MSC_VER <= 1900 + insert_hack_t::insert(*stream, in); +#else + operator<<(*stream, in); +#endif + } + }; + +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) +// NOLINTBEGIN(*-avoid-c-arrays) + template + struct filldata { + static void fill(std::ostream* stream, const T(&in)[N]) { + *stream << "["; + for (size_t i = 0; i < N; i++) { + if (i != 0) { *stream << ", "; } + *stream << (DOCTEST_STRINGIFY(in[i])); + } + *stream << "]"; + } + }; +// NOLINTEND(*-avoid-c-arrays) +DOCTEST_MSVC_SUPPRESS_WARNING_POP + + // Specialized since we don't want the terminating null byte! +// NOLINTBEGIN(*-avoid-c-arrays) + template + struct filldata { + static void fill(std::ostream* stream, const char (&in)[N]) { + *stream << String(in, in[N - 1] ? N : N - 1); + } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + }; +// NOLINTEND(*-avoid-c-arrays) + + template <> + struct filldata { + static void fill(std::ostream* stream, const void* in); + }; + + template + struct filldata { +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180) + static void fill(std::ostream* stream, const T* in) { +DOCTEST_MSVC_SUPPRESS_WARNING_POP +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast") + filldata::fill(stream, +#if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0) + reinterpret_cast(in) +#else + *reinterpret_cast(&in) +#endif + ); +DOCTEST_CLANG_SUPPRESS_WARNING_POP + } + }; +} + +struct DOCTEST_INTERFACE Approx +{ + Approx(double value); + + Approx operator()(double value) const; + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template + explicit Approx(const T& value, + typename detail::types::enable_if::value>::type* = + static_cast(nullptr)) { + *this = static_cast(value); + } +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + Approx& epsilon(double newEpsilon); + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template + typename std::enable_if::value, Approx&>::type epsilon( + const T& newEpsilon) { + m_epsilon = static_cast(newEpsilon); + return *this; + } +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + Approx& scale(double newScale); + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template + typename std::enable_if::value, Approx&>::type scale( + const T& newScale) { + m_scale = static_cast(newScale); + return *this; + } +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + // clang-format off + DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator==(const Approx & lhs, double rhs); + DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator!=(const Approx & lhs, double rhs); + DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator<=(const Approx & lhs, double rhs); + DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator>=(const Approx & lhs, double rhs); + DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator< (const Approx & lhs, double rhs); + DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator> (const Approx & lhs, double rhs); + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#define DOCTEST_APPROX_PREFIX \ + template friend typename std::enable_if::value, bool>::type + + DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast(lhs), rhs); } + DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); } + DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); } + DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); } + DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value && lhs != rhs; } + DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) && lhs != rhs; } + DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value && lhs != rhs; } + DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) && lhs != rhs; } +#undef DOCTEST_APPROX_PREFIX +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + // clang-format on + + double m_epsilon; + double m_scale; + double m_value; +}; + +DOCTEST_INTERFACE String toString(const Approx& in); + +DOCTEST_INTERFACE const ContextOptions* getContextOptions(); + +template +struct DOCTEST_INTERFACE_DECL IsNaN +{ + F value; bool flipped; + IsNaN(F f, bool flip = false) : value(f), flipped(flip) { } + IsNaN operator!() const { return { value, !flipped }; } + operator bool() const; +}; +#ifndef __MINGW32__ +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +#endif +DOCTEST_INTERFACE String toString(IsNaN in); +DOCTEST_INTERFACE String toString(IsNaN in); +DOCTEST_INTERFACE String toString(IsNaN in); + +#ifndef DOCTEST_CONFIG_DISABLE + +namespace detail { + // clang-format off +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + template struct decay_array { using type = T; }; + template struct decay_array { using type = T*; }; + template struct decay_array { using type = T*; }; + + template struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; }; + template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; + template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; + + template struct can_use_op : public not_char_pointer::type> {}; +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + // clang-format on + + struct DOCTEST_INTERFACE TestFailureException + { + }; + + DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at); + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + DOCTEST_NORETURN +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + DOCTEST_INTERFACE void throwException(); + + struct DOCTEST_INTERFACE Subcase + { + SubcaseSignature m_signature; + bool m_entered = false; + + Subcase(const String& name, const char* file, int line); + Subcase(const Subcase&) = delete; + Subcase(Subcase&&) = delete; + Subcase& operator=(const Subcase&) = delete; + Subcase& operator=(Subcase&&) = delete; + ~Subcase(); + + operator bool() const; + + private: + bool checkFilters(); + }; + + template + String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op, + const DOCTEST_REF_WRAP(R) rhs) { + return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); + } + +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") +#endif + +// This will check if there is any way it could find a operator like member or friend and uses it. +// If not it doesn't find the operator or if the operator at global scope is defined after +// this template, the template won't be instantiated due to SFINAE. Once the template is not +// instantiated it can look for global operator using normal conversions. +#ifdef __NVCC__ +#define SFINAE_OP(ret,op) ret +#else +#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{}) +#endif + +#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ + template \ + DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \ + bool res = op_macro(doctest::detail::forward(lhs), doctest::detail::forward(rhs)); \ + if(m_at & assertType::is_false) \ + res = !res; \ + if(!res || doctest::getContextOptions()->success) \ + return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \ + return Result(res); \ + } + + // more checks could be added - like in Catch: + // https://github.com/catchorg/Catch2/pull/1480/files + // https://github.com/catchorg/Catch2/pull/1481/files +#define DOCTEST_FORBIT_EXPRESSION(rt, op) \ + template \ + rt& operator op(const R&) { \ + static_assert(deferred_false::value, \ + "Expression Too Complex Please Rewrite As Binary Comparison!"); \ + return *this; \ + } + + struct DOCTEST_INTERFACE Result // NOLINT(*-member-init) + { + bool m_passed; + String m_decomp; + + Result() = default; // TODO: Why do we need this? (To remove NOLINT) + Result(bool passed, const String& decomposition = String()); + + // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Result, &) + DOCTEST_FORBIT_EXPRESSION(Result, ^) + DOCTEST_FORBIT_EXPRESSION(Result, |) + DOCTEST_FORBIT_EXPRESSION(Result, &&) + DOCTEST_FORBIT_EXPRESSION(Result, ||) + DOCTEST_FORBIT_EXPRESSION(Result, ==) + DOCTEST_FORBIT_EXPRESSION(Result, !=) + DOCTEST_FORBIT_EXPRESSION(Result, <) + DOCTEST_FORBIT_EXPRESSION(Result, >) + DOCTEST_FORBIT_EXPRESSION(Result, <=) + DOCTEST_FORBIT_EXPRESSION(Result, >=) + DOCTEST_FORBIT_EXPRESSION(Result, =) + DOCTEST_FORBIT_EXPRESSION(Result, +=) + DOCTEST_FORBIT_EXPRESSION(Result, -=) + DOCTEST_FORBIT_EXPRESSION(Result, *=) + DOCTEST_FORBIT_EXPRESSION(Result, /=) + DOCTEST_FORBIT_EXPRESSION(Result, %=) + DOCTEST_FORBIT_EXPRESSION(Result, <<=) + DOCTEST_FORBIT_EXPRESSION(Result, >>=) + DOCTEST_FORBIT_EXPRESSION(Result, &=) + DOCTEST_FORBIT_EXPRESSION(Result, ^=) + DOCTEST_FORBIT_EXPRESSION(Result, |=) + }; + +#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH + DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") + DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") + + DOCTEST_GCC_SUPPRESS_WARNING_PUSH + DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") + DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") + + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH + // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389 + DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch + DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch + DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch + //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation + +#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + + // clang-format off +#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_COMPARISON_RETURN_TYPE bool +#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if::value || can_use_op::value, bool>::type + inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); } + inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); } + inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); } + inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); } + inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); } + inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); } +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + // clang-format on + +#define DOCTEST_RELATIONAL_OP(name, op) \ + template \ + DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \ + const DOCTEST_REF_WRAP(R) rhs) { \ + return lhs op rhs; \ + } + + DOCTEST_RELATIONAL_OP(eq, ==) + DOCTEST_RELATIONAL_OP(ne, !=) + DOCTEST_RELATIONAL_OP(lt, <) + DOCTEST_RELATIONAL_OP(gt, >) + DOCTEST_RELATIONAL_OP(le, <=) + DOCTEST_RELATIONAL_OP(ge, >=) + +#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_CMP_EQ(l, r) l == r +#define DOCTEST_CMP_NE(l, r) l != r +#define DOCTEST_CMP_GT(l, r) l > r +#define DOCTEST_CMP_LT(l, r) l < r +#define DOCTEST_CMP_GE(l, r) l >= r +#define DOCTEST_CMP_LE(l, r) l <= r +#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_CMP_EQ(l, r) eq(l, r) +#define DOCTEST_CMP_NE(l, r) ne(l, r) +#define DOCTEST_CMP_GT(l, r) gt(l, r) +#define DOCTEST_CMP_LT(l, r) lt(l, r) +#define DOCTEST_CMP_GE(l, r) ge(l, r) +#define DOCTEST_CMP_LE(l, r) le(l, r) +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + + template + // cppcheck-suppress copyCtorAndEqOperator + struct Expression_lhs + { + L lhs; + assertType::Enum m_at; + + explicit Expression_lhs(L&& in, assertType::Enum at) + : lhs(static_cast(in)) + , m_at(at) {} + + DOCTEST_NOINLINE operator Result() { +// this is needed only for MSVC 2015 +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool + bool res = static_cast(lhs); +DOCTEST_MSVC_SUPPRESS_WARNING_POP + if(m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional + res = !res; + } + + if(!res || getContextOptions()->success) { + return { res, (DOCTEST_STRINGIFY(lhs)) }; + } + return { res }; + } + + /* This is required for user-defined conversions from Expression_lhs to L */ + operator L() const { return lhs; } + + // clang-format off + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional + // clang-format on + + // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) + // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the + // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression... + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>) + }; + +#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + +#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) +DOCTEST_CLANG_SUPPRESS_WARNING_POP +#endif + + struct DOCTEST_INTERFACE ExpressionDecomposer + { + assertType::Enum m_at; + + ExpressionDecomposer(assertType::Enum at); + + // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table) + // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now... + // https://github.com/catchorg/Catch2/issues/870 + // https://github.com/catchorg/Catch2/issues/565 + template + Expression_lhs operator<<(L&& operand) { + return Expression_lhs(static_cast(operand), m_at); + } + + template ::value,void >::type* = nullptr> + Expression_lhs operator<<(const L &operand) { + return Expression_lhs(operand, m_at); + } + }; + + struct DOCTEST_INTERFACE TestSuite + { + const char* m_test_suite = nullptr; + const char* m_description = nullptr; + bool m_skip = false; + bool m_no_breaks = false; + bool m_no_output = false; + bool m_may_fail = false; + bool m_should_fail = false; + int m_expected_failures = 0; + double m_timeout = 0; + + TestSuite& operator*(const char* in); + + template + TestSuite& operator*(const T& in) { + in.fill(*this); + return *this; + } + }; + + using funcType = void (*)(); + + struct DOCTEST_INTERFACE TestCase : public TestCaseData + { + funcType m_test; // a function pointer to the test case + + String m_type; // for templated test cases - gets appended to the real name + int m_template_id; // an ID used to distinguish between the different versions of a templated test case + String m_full_name; // contains the name (only for templated test cases!) + the template type + + TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, + const String& type = String(), int template_id = -1); + + TestCase(const TestCase& other); + TestCase(TestCase&&) = delete; + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function + TestCase& operator=(const TestCase& other); + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + TestCase& operator=(TestCase&&) = delete; + + TestCase& operator*(const char* in); + + template + TestCase& operator*(const T& in) { + in.fill(*this); + return *this; + } + + bool operator<(const TestCase& other) const; + + ~TestCase() = default; + }; + + // forward declarations of functions used by the macros + DOCTEST_INTERFACE int regTest(const TestCase& tc); + DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts); + DOCTEST_INTERFACE bool isDebuggerActive(); + + template + int instantiationHelper(const T&) { return 0; } + + namespace binaryAssertComparison { + enum Enum + { + eq = 0, + ne, + gt, + lt, + ge, + le + }; + } // namespace binaryAssertComparison + + // clang-format off + template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } }; + +#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \ + template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } }; + // clang-format on + + DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq) + DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne) + DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt) + DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt) + DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) + DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) + + struct DOCTEST_INTERFACE ResultBuilder : public AssertData + { + ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type = "", const String& exception_string = ""); + + ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const Contains& exception_string); + + void setResult(const Result& res); + + template + DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) { + m_failed = !RelationalComparator()(lhs, rhs); + if (m_failed || getContextOptions()->success) { + m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); + } + return !m_failed; + } + + template + DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) { + m_failed = !val; + + if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional + m_failed = !m_failed; + } + + if (m_failed || getContextOptions()->success) { + m_decomp = (DOCTEST_STRINGIFY(val)); + } + + return !m_failed; + } + + void translateException(); + + bool log(); + void react() const; + }; + + namespace assertAction { + enum Enum + { + nothing = 0, + dbgbreak = 1, + shouldthrow = 2 + }; + } // namespace assertAction + + DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad); + + DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line, + const char* expr, const Result& result); + +#define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \ + do { \ + if(!is_running_in_test) { \ + if(failed) { \ + ResultBuilder rb(at, file, line, expr); \ + rb.m_failed = failed; \ + rb.m_decomp = decomp; \ + failed_out_of_a_testing_context(rb); \ + if(isDebuggerActive() && !getContextOptions()->no_breaks) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + if(checkIfShouldThrow(at)) \ + throwException(); \ + } \ + return !failed; \ + } \ + } while(false) + +#define DOCTEST_ASSERT_IN_TESTS(decomp) \ + ResultBuilder rb(at, file, line, expr); \ + rb.m_failed = failed; \ + if(rb.m_failed || getContextOptions()->success) \ + rb.m_decomp = decomp; \ + if(rb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + if(rb.m_failed && checkIfShouldThrow(at)) \ + throwException() + + template + DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line, + const char* expr, const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) { + bool failed = !RelationalComparator()(lhs, rhs); + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + return !failed; + } + + template + DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line, + const char* expr, const DOCTEST_REF_WRAP(L) val) { + bool failed = !val; + + if(at & assertType::is_false) //!OCLINT bitwise operator in conditional + failed = !failed; + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); + DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); + return !failed; + } + + struct DOCTEST_INTERFACE IExceptionTranslator + { + DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) + virtual bool translate(String&) const = 0; + }; + + template + class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class + { + public: + explicit ExceptionTranslator(String (*translateFunction)(T)) + : m_translateFunction(translateFunction) {} + + bool translate(String& res) const override { +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + try { + throw; // lgtm [cpp/rethrow-no-exception] + // cppcheck-suppress catchExceptionByValue + } catch(const T& ex) { + res = m_translateFunction(ex); //!OCLINT parameter reassignment + return true; + } catch(...) {} //!OCLINT - empty catch statement +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + static_cast(res); // to silence -Wunused-parameter + return false; + } + + private: + String (*m_translateFunction)(T); + }; + + DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et); + + // ContextScope base class used to allow implementing methods of ContextScope + // that don't depend on the template parameter in doctest.cpp. + struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope { + ContextScopeBase(const ContextScopeBase&) = delete; + + ContextScopeBase& operator=(const ContextScopeBase&) = delete; + ContextScopeBase& operator=(ContextScopeBase&&) = delete; + + ~ContextScopeBase() override = default; + + protected: + ContextScopeBase(); + ContextScopeBase(ContextScopeBase&& other) noexcept; + + void destroy(); + bool need_to_destroy{true}; + }; + + template class ContextScope : public ContextScopeBase + { + L lambda_; + + public: + explicit ContextScope(const L &lambda) : lambda_(lambda) {} + explicit ContextScope(L&& lambda) : lambda_(static_cast(lambda)) { } + + ContextScope(const ContextScope&) = delete; + ContextScope(ContextScope&&) noexcept = default; + + ContextScope& operator=(const ContextScope&) = delete; + ContextScope& operator=(ContextScope&&) = delete; + + void stringify(std::ostream* s) const override { lambda_(s); } + + ~ContextScope() override { + if (need_to_destroy) { + destroy(); + } + } + }; + + struct DOCTEST_INTERFACE MessageBuilder : public MessageData + { + std::ostream* m_stream; + bool logged = false; + + MessageBuilder(const char* file, int line, assertType::Enum severity); + + MessageBuilder(const MessageBuilder&) = delete; + MessageBuilder(MessageBuilder&&) = delete; + + MessageBuilder& operator=(const MessageBuilder&) = delete; + MessageBuilder& operator=(MessageBuilder&&) = delete; + + ~MessageBuilder(); + + // the preferred way of chaining parameters for stringification +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) + template + MessageBuilder& operator,(const T& in) { + *m_stream << (DOCTEST_STRINGIFY(in)); + return *this; + } +DOCTEST_MSVC_SUPPRESS_WARNING_POP + + // kept here just for backwards-compatibility - the comma operator should be preferred now + template + MessageBuilder& operator<<(const T& in) { return this->operator,(in); } + + // the `,` operator has the lowest operator precedence - if `<<` is used by the user then + // the `,` operator will be called last which is not what we want and thus the `*` operator + // is used first (has higher operator precedence compared to `<<`) so that we guarantee that + // an operator of the MessageBuilder class is called first before the rest of the parameters + template + MessageBuilder& operator*(const T& in) { return this->operator,(in); } + + bool log(); + void react(); + }; + + template + ContextScope MakeContextScope(const L &lambda) { + return ContextScope(lambda); + } +} // namespace detail + +#define DOCTEST_DEFINE_DECORATOR(name, type, def) \ + struct name \ + { \ + type data; \ + name(type in = def) \ + : data(in) {} \ + void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; } \ + void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \ + } + +DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); +DOCTEST_DEFINE_DECORATOR(description, const char*, ""); +DOCTEST_DEFINE_DECORATOR(skip, bool, true); +DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); +DOCTEST_DEFINE_DECORATOR(no_output, bool, true); +DOCTEST_DEFINE_DECORATOR(timeout, double, 0); +DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); +DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); +DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); + +template +int registerExceptionTranslator(String (*translateFunction)(T)) { + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") + static detail::ExceptionTranslator exceptionTranslator(translateFunction); + DOCTEST_CLANG_SUPPRESS_WARNING_POP + detail::registerExceptionTranslatorImpl(&exceptionTranslator); + return 0; +} + +} // namespace doctest + +// in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro +// introduces an anonymous namespace in which getCurrentTestSuite gets overridden +namespace doctest_detail_test_suite_ns { +DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite(); +} // namespace doctest_detail_test_suite_ns + +namespace doctest { +#else // DOCTEST_CONFIG_DISABLE +template +int registerExceptionTranslator(String (*)(T)) { + return 0; +} +#endif // DOCTEST_CONFIG_DISABLE + +namespace detail { + using assert_handler = void (*)(const AssertData&); + struct ContextState; +} // namespace detail + +class DOCTEST_INTERFACE Context +{ + detail::ContextState* p; + + void parseArgs(int argc, const char* const* argv, bool withDefaults = false); + +public: + explicit Context(int argc = 0, const char* const* argv = nullptr); + + Context(const Context&) = delete; + Context(Context&&) = delete; + + Context& operator=(const Context&) = delete; + Context& operator=(Context&&) = delete; + + ~Context(); // NOLINT(performance-trivially-destructible) + + void applyCommandLine(int argc, const char* const* argv); + + void addFilter(const char* filter, const char* value); + void clearFilters(); + void setOption(const char* option, bool value); + void setOption(const char* option, int value); + void setOption(const char* option, const char* value); + + bool shouldExit(); + + void setAsDefaultForAssertsOutOfTestCases(); + + void setAssertHandler(detail::assert_handler ah); + + void setCout(std::ostream* out); + + int run(); +}; + +namespace TestCaseFailureReason { + enum Enum + { + None = 0, + AssertFailure = 1, // an assertion has failed in the test case + Exception = 2, // test case threw an exception + Crash = 4, // a crash... + TooManyFailedAsserts = 8, // the abort-after option + Timeout = 16, // see the timeout decorator + ShouldHaveFailedButDidnt = 32, // see the should_fail decorator + ShouldHaveFailedAndDid = 64, // see the should_fail decorator + DidntFailExactlyNumTimes = 128, // see the expected_failures decorator + FailedExactlyNumTimes = 256, // see the expected_failures decorator + CouldHaveFailedAndDid = 512 // see the may_fail decorator + }; +} // namespace TestCaseFailureReason + +struct DOCTEST_INTERFACE CurrentTestCaseStats +{ + int numAssertsCurrentTest; + int numAssertsFailedCurrentTest; + double seconds; + int failure_flags; // use TestCaseFailureReason::Enum + bool testCaseSuccess; +}; + +struct DOCTEST_INTERFACE TestCaseException +{ + String error_string; + bool is_crash; +}; + +struct DOCTEST_INTERFACE TestRunStats +{ + unsigned numTestCases; + unsigned numTestCasesPassingFilters; + unsigned numTestSuitesPassingFilters; + unsigned numTestCasesFailed; + int numAsserts; + int numAssertsFailed; +}; + +struct QueryData +{ + const TestRunStats* run_stats = nullptr; + const TestCaseData** data = nullptr; + unsigned num_data = 0; +}; + +struct DOCTEST_INTERFACE IReporter +{ + // The constructor has to accept "const ContextOptions&" as a single argument + // which has most of the options for the run + a pointer to the stdout stream + // Reporter(const ContextOptions& in) + + // called when a query should be reported (listing test cases, printing the version, etc.) + virtual void report_query(const QueryData&) = 0; + + // called when the whole test run starts + virtual void test_run_start() = 0; + // called when the whole test run ends (caching a pointer to the input doesn't make sense here) + virtual void test_run_end(const TestRunStats&) = 0; + + // called when a test case is started (safe to cache a pointer to the input) + virtual void test_case_start(const TestCaseData&) = 0; + // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input) + virtual void test_case_reenter(const TestCaseData&) = 0; + // called when a test case has ended + virtual void test_case_end(const CurrentTestCaseStats&) = 0; + + // called when an exception is thrown from the test case (or it crashes) + virtual void test_case_exception(const TestCaseException&) = 0; + + // called whenever a subcase is entered (don't cache pointers to the input) + virtual void subcase_start(const SubcaseSignature&) = 0; + // called whenever a subcase is exited (don't cache pointers to the input) + virtual void subcase_end() = 0; + + // called for each assert (don't cache pointers to the input) + virtual void log_assert(const AssertData&) = 0; + // called for each message (don't cache pointers to the input) + virtual void log_message(const MessageData&) = 0; + + // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator + // or isn't in the execution range (between first and last) (safe to cache a pointer to the input) + virtual void test_case_skipped(const TestCaseData&) = 0; + + DOCTEST_DECLARE_INTERFACE(IReporter) + + // can obtain all currently active contexts and stringify them if one wishes to do so + static int get_num_active_contexts(); + static const IContextScope* const* get_active_contexts(); + + // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown + static int get_num_stringified_contexts(); + static const String* get_stringified_contexts(); +}; + +namespace detail { + using reporterCreatorFunc = IReporter* (*)(const ContextOptions&); + + DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter); + + template + IReporter* reporterCreator(const ContextOptions& o) { + return new Reporter(o); + } +} // namespace detail + +template +int registerReporter(const char* name, int priority, bool isReporter) { + detail::registerReporterImpl(name, priority, detail::reporterCreator, isReporter); + return 0; +} +} // namespace doctest + +#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES +#define DOCTEST_FUNC_EMPTY [] { return false; }() +#else +#define DOCTEST_FUNC_EMPTY (void)0 +#endif + +// if registering is not disabled +#ifndef DOCTEST_CONFIG_DISABLE + +#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES +#define DOCTEST_FUNC_SCOPE_BEGIN [&] +#define DOCTEST_FUNC_SCOPE_END () +#define DOCTEST_FUNC_SCOPE_RET(v) return v +#else +#define DOCTEST_FUNC_SCOPE_BEGIN do +#define DOCTEST_FUNC_SCOPE_END while(false) +#define DOCTEST_FUNC_SCOPE_RET(v) (void)0 +#endif + +// common code in asserts - for convenience +#define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \ + if(b.log()) DOCTEST_BREAK_INTO_DEBUGGER(); \ + b.react(); \ + DOCTEST_FUNC_SCOPE_RET(!b.m_failed) + +#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS +#define DOCTEST_WRAP_IN_TRY(x) x; +#else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS +#define DOCTEST_WRAP_IN_TRY(x) \ + try { \ + x; \ + } catch(...) { DOCTEST_RB.translateException(); } +#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS + +#ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS +#define DOCTEST_CAST_TO_VOID(...) \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \ + static_cast(__VA_ARGS__); \ + DOCTEST_GCC_SUPPRESS_WARNING_POP +#else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS +#define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__; +#endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS + +// registers the test by initializing a dummy var with a function +#define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \ + global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \ + doctest::detail::regTest( \ + doctest::detail::TestCase( \ + f, __FILE__, __LINE__, \ + doctest_detail_test_suite_ns::getCurrentTestSuite()) * \ + decorators)) + +#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \ + namespace { /* NOLINT */ \ + struct der : public base \ + { \ + void f(); \ + }; \ + static DOCTEST_INLINE_NOINLINE void func() { \ + der v; \ + v.f(); \ + } \ + DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \ + } \ + DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers) + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \ + static void f(); \ + DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \ + static void f() + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \ + static doctest::detail::funcType proxy() { return f; } \ + DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \ + static void f() + +// for registering tests +#define DOCTEST_TEST_CASE(decorators) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) + +// for registering tests in classes - requires C++17 for inline variables! +#if DOCTEST_CPLUSPLUS >= 201703L +#define DOCTEST_TEST_CASE_CLASS(decorators) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \ + decorators) +#else // DOCTEST_TEST_CASE_CLASS +#define DOCTEST_TEST_CASE_CLASS(...) \ + TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER +#endif // DOCTEST_TEST_CASE_CLASS + +// for registering tests with a fixture +#define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \ + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) + +// for converting types to strings without the header and demangling +#define DOCTEST_TYPE_TO_STRING_AS(str, ...) \ + namespace doctest { \ + template <> \ + inline String toString<__VA_ARGS__>() { \ + return str; \ + } \ + } \ + static_assert(true, "") + +#define DOCTEST_TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__) + +#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \ + template \ + static void func(); \ + namespace { /* NOLINT */ \ + template \ + struct iter; \ + template \ + struct iter> \ + { \ + iter(const char* file, unsigned line, int index) { \ + doctest::detail::regTest(doctest::detail::TestCase(func, file, line, \ + doctest_detail_test_suite_ns::getCurrentTestSuite(), \ + doctest::toString(), \ + int(line) * 1000 + index) \ + * dec); \ + iter>(file, line, index + 1); \ + } \ + }; \ + template <> \ + struct iter> \ + { \ + iter(const char*, unsigned, int) {} \ + }; \ + } \ + template \ + static void func() + +#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \ + DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)) + +#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \ + doctest::detail::instantiationHelper( \ + DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0))) + +#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \ + static_assert(true, "") + +#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \ + static_assert(true, "") + +#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \ + template \ + static void anon() + +#define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) + +// for subcases +#define DOCTEST_SUBCASE(name) \ + if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \ + doctest::detail::Subcase(name, __FILE__, __LINE__)) + +// for grouping tests in test suites by using code blocks +#define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \ + namespace ns_name { namespace doctest_detail_test_suite_ns { \ + static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() noexcept { \ + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ + static doctest::detail::TestSuite data{}; \ + static bool inited = false; \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + if(!inited) { \ + data* decorators; \ + inited = true; \ + } \ + return data; \ + } \ + } \ + } \ + namespace ns_name + +#define DOCTEST_TEST_SUITE(decorators) \ + DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_)) + +// for starting a testsuite block +#define DOCTEST_TEST_SUITE_BEGIN(decorators) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \ + static_assert(true, "") + +// for ending a testsuite block +#define DOCTEST_TEST_SUITE_END \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \ + using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int + +// for registering exception translators +#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \ + inline doctest::String translatorName(signature); \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerExceptionTranslator(translatorName)) \ + doctest::String translatorName(signature) + +#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ + DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \ + signature) + +// for registering reporters +#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerReporter(name, priority, true)) \ + static_assert(true, "") + +// for registering listeners +#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerReporter(name, priority, false)) \ + static_assert(true, "") + +// clang-format off +// for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557 +#define DOCTEST_INFO(...) \ + DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_), \ + DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_), \ + __VA_ARGS__) +// clang-format on + +#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ + auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \ + [&](std::ostream* s_name) { \ + doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ + mb_name.m_stream = s_name; \ + mb_name * __VA_ARGS__; \ + }) + +#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) + +#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ + mb * __VA_ARGS__; \ + if(mb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + mb.react(); \ + } DOCTEST_FUNC_SCOPE_END + +// clang-format off +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +// clang-format on + +#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) + +#define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility. + +#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +#define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ + /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \ + doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ + << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP + +#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \ + } DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + +#define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY( \ + DOCTEST_RB.binary_assert( \ + __VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } DOCTEST_FUNC_SCOPE_END + +#define DOCTEST_UNARY_ASSERT(assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } DOCTEST_FUNC_SCOPE_END + +#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +// necessary for _MESSAGE +#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1 + +#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ + doctest::detail::decomp_assert( \ + doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \ + doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ + << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP + +#define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \ + doctest::detail::binary_assert( \ + doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__) + +#define DOCTEST_UNARY_ASSERT(assert_type, ...) \ + doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ + #__VA_ARGS__, __VA_ARGS__) + +#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__) +#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__) +#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__) +#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__) +#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__) +#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__) + +// clang-format off +#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END +// clang-format on + +#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__) +#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__) +#define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__) +#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__) +#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__) +#define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__) +#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__) +#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__) +#define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__) +#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__) +#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__) +#define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__) +#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__) +#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__) +#define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__) +#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__) +#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__) +#define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__) + +#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__) +#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__) +#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__) +#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__) +#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) +#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__) + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + +#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + if(!doctest::getContextOptions()->no_throw) { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #expr, #__VA_ARGS__, message); \ + try { \ + DOCTEST_CAST_TO_VOID(expr) \ + } catch(const typename doctest::detail::types::remove_const< \ + typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type&) {\ + DOCTEST_RB.translateException(); \ + DOCTEST_RB.m_threw_as = true; \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } else { /* NOLINT(*-else-after-return) */ \ + DOCTEST_FUNC_SCOPE_RET(false); \ + } \ + } DOCTEST_FUNC_SCOPE_END + +#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + if(!doctest::getContextOptions()->no_throw) { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, expr_str, "", __VA_ARGS__); \ + try { \ + DOCTEST_CAST_TO_VOID(expr) \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } else { /* NOLINT(*-else-after-return) */ \ + DOCTEST_FUNC_SCOPE_RET(false); \ + } \ + } DOCTEST_FUNC_SCOPE_END + +#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + try { \ + DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } DOCTEST_FUNC_SCOPE_END + +// clang-format off +#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "") +#define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "") +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "") + +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__) + +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__) + +#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__) + +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__) +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__) +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__) + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END +// clang-format on + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +// ================================================================================================= +// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! == +// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! == +// ================================================================================================= +#else // DOCTEST_CONFIG_DISABLE + +#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \ + namespace /* NOLINT */ { \ + template \ + struct der : public base \ + { void f(); }; \ + } \ + template \ + inline void der::f() + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \ + template \ + static inline void f() + +// for registering tests +#define DOCTEST_TEST_CASE(name) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + +// for registering tests in classes +#define DOCTEST_TEST_CASE_CLASS(name) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + +// for registering tests with a fixture +#define DOCTEST_TEST_CASE_FIXTURE(x, name) \ + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + +// for converting types to strings without the header and demangling +#define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "") +#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "") + +// for typed tests +#define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \ + template \ + inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() + +#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \ + template \ + inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() + +#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "") +#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "") + +// for subcases +#define DOCTEST_SUBCASE(name) + +// for a testsuite block +#define DOCTEST_TEST_SUITE(name) namespace // NOLINT + +// for starting a testsuite block +#define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "") + +// for ending a testsuite block +#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int + +#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ + template \ + static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature) + +#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) +#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) + +#define DOCTEST_INFO(...) (static_cast(0)) +#define DOCTEST_CAPTURE(x) (static_cast(0)) +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_MESSAGE(...) (static_cast(0)) +#define DOCTEST_FAIL_CHECK(...) (static_cast(0)) +#define DOCTEST_FAIL(...) (static_cast(0)) + +#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) \ + && defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES) + +#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }() + +#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() + +namespace doctest { +namespace detail { +#define DOCTEST_RELATIONAL_OP(name, op) \ + template \ + bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; } + + DOCTEST_RELATIONAL_OP(eq, ==) + DOCTEST_RELATIONAL_OP(ne, !=) + DOCTEST_RELATIONAL_OP(lt, <) + DOCTEST_RELATIONAL_OP(gt, >) + DOCTEST_RELATIONAL_OP(le, <=) + DOCTEST_RELATIONAL_OP(ge, >=) +} // namespace detail +} // namespace doctest + +#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + +#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) [] { static_assert(false, "Exception translation is not available when doctest is disabled."); return false; }() +#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) + +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) + +#define DOCTEST_WARN_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_CHECK_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_REQUIRE_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_WARN_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_CHECK_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_WARN_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_CHECK_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_REQUIRE_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +#else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED + +#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + +#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +#endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED + +#endif // DOCTEST_CONFIG_DISABLE + +#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS + +#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS +#define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY +#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS +#define DOCTEST_EXCEPTION_EMPTY_FUNC [] { static_assert(false, "Exceptions are disabled! " \ + "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to compile with exceptions disabled."); return false; }() + +#undef DOCTEST_REQUIRE +#undef DOCTEST_REQUIRE_FALSE +#undef DOCTEST_REQUIRE_MESSAGE +#undef DOCTEST_REQUIRE_FALSE_MESSAGE +#undef DOCTEST_REQUIRE_EQ +#undef DOCTEST_REQUIRE_NE +#undef DOCTEST_REQUIRE_GT +#undef DOCTEST_REQUIRE_LT +#undef DOCTEST_REQUIRE_GE +#undef DOCTEST_REQUIRE_LE +#undef DOCTEST_REQUIRE_UNARY +#undef DOCTEST_REQUIRE_UNARY_FALSE + +#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS + +#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +// clang-format off +// KEPT FOR BACKWARDS COMPATIBILITY - FORWARDING TO THE RIGHT MACROS +#define DOCTEST_FAST_WARN_EQ DOCTEST_WARN_EQ +#define DOCTEST_FAST_CHECK_EQ DOCTEST_CHECK_EQ +#define DOCTEST_FAST_REQUIRE_EQ DOCTEST_REQUIRE_EQ +#define DOCTEST_FAST_WARN_NE DOCTEST_WARN_NE +#define DOCTEST_FAST_CHECK_NE DOCTEST_CHECK_NE +#define DOCTEST_FAST_REQUIRE_NE DOCTEST_REQUIRE_NE +#define DOCTEST_FAST_WARN_GT DOCTEST_WARN_GT +#define DOCTEST_FAST_CHECK_GT DOCTEST_CHECK_GT +#define DOCTEST_FAST_REQUIRE_GT DOCTEST_REQUIRE_GT +#define DOCTEST_FAST_WARN_LT DOCTEST_WARN_LT +#define DOCTEST_FAST_CHECK_LT DOCTEST_CHECK_LT +#define DOCTEST_FAST_REQUIRE_LT DOCTEST_REQUIRE_LT +#define DOCTEST_FAST_WARN_GE DOCTEST_WARN_GE +#define DOCTEST_FAST_CHECK_GE DOCTEST_CHECK_GE +#define DOCTEST_FAST_REQUIRE_GE DOCTEST_REQUIRE_GE +#define DOCTEST_FAST_WARN_LE DOCTEST_WARN_LE +#define DOCTEST_FAST_CHECK_LE DOCTEST_CHECK_LE +#define DOCTEST_FAST_REQUIRE_LE DOCTEST_REQUIRE_LE + +#define DOCTEST_FAST_WARN_UNARY DOCTEST_WARN_UNARY +#define DOCTEST_FAST_CHECK_UNARY DOCTEST_CHECK_UNARY +#define DOCTEST_FAST_REQUIRE_UNARY DOCTEST_REQUIRE_UNARY +#define DOCTEST_FAST_WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE +#define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE +#define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE + +#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__) +// clang-format on + +// BDD style macros +// clang-format off +#define DOCTEST_SCENARIO(name) DOCTEST_TEST_CASE(" Scenario: " name) +#define DOCTEST_SCENARIO_CLASS(name) DOCTEST_TEST_CASE_CLASS(" Scenario: " name) +#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__) +#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id) + +#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name) +#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name) +#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name) +#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name) +#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name) +// clang-format on + +// == SHORT VERSIONS OF THE MACROS +#ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES + +#define TEST_CASE(name) DOCTEST_TEST_CASE(name) +#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name) +#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name) +#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__) +#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__) +#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id) +#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__) +#define SUBCASE(name) DOCTEST_SUBCASE(name) +#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators) +#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name) +#define TEST_SUITE_END DOCTEST_TEST_SUITE_END +#define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) +#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter) +#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter) +#define INFO(...) DOCTEST_INFO(__VA_ARGS__) +#define CAPTURE(x) DOCTEST_CAPTURE(x) +#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__) +#define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__) +#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__) +#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__) +#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__) +#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__) +#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__) + +#define WARN(...) DOCTEST_WARN(__VA_ARGS__) +#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__) +#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__) +#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__) +#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__) +#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__) +#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__) +#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__) +#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__) +#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__) +#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__) +#define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__) +#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__) +#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__) +#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__) +#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__) + +#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__) +#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__) +#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__) +#define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__) +#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__) +#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__) +#define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__) +#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__) +#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__) +#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__) +#define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__) +#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__) + +#define SCENARIO(name) DOCTEST_SCENARIO(name) +#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name) +#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__) +#define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) +#define GIVEN(name) DOCTEST_GIVEN(name) +#define WHEN(name) DOCTEST_WHEN(name) +#define AND_WHEN(name) DOCTEST_AND_WHEN(name) +#define THEN(name) DOCTEST_THEN(name) +#define AND_THEN(name) DOCTEST_AND_THEN(name) + +#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__) +#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__) +#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__) +#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__) +#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__) +#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__) +#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__) +#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__) +#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__) +#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__) +#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__) +#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__) +#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__) +#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__) +#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__) +#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__) +#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__) +#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__) +#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__) +#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__) +#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__) +#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__) +#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__) + +// KEPT FOR BACKWARDS COMPATIBILITY +#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) +#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) +#define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__) +#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__) +#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__) +#define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__) +#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__) +#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__) +#define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__) +#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__) +#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__) +#define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__) +#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__) +#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__) +#define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__) +#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__) +#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__) +#define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__) + +#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__) +#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__) +#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__) +#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__) +#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__) + +#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__) + +#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES + +#ifndef DOCTEST_CONFIG_DISABLE + +// this is here to clear the 'current test suite' for the current translation unit - at the top +DOCTEST_TEST_SUITE_END(); + +#endif // DOCTEST_CONFIG_DISABLE + +DOCTEST_CLANG_SUPPRESS_WARNING_POP +DOCTEST_MSVC_SUPPRESS_WARNING_POP +DOCTEST_GCC_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_POP + +#endif // DOCTEST_LIBRARY_INCLUDED + +#ifndef DOCTEST_SINGLE_HEADER +#define DOCTEST_SINGLE_HEADER +#endif // DOCTEST_SINGLE_HEADER + +#if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER) + +#ifndef DOCTEST_SINGLE_HEADER +#include "doctest_fwd.h" +#endif // DOCTEST_SINGLE_HEADER + +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros") + +#ifndef DOCTEST_LIBRARY_IMPLEMENTATION +#define DOCTEST_LIBRARY_IMPLEMENTATION + +DOCTEST_CLANG_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH + +DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path") + +DOCTEST_GCC_SUPPRESS_WARNING_PUSH +DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") +DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") +DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers") +DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces") +DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch") +DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum") +DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default") +DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations") +DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast") +DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function") +DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance") +DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute") + +DOCTEST_MSVC_SUPPRESS_WARNING_PUSH +DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data +DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled +DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified +DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal +DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch +DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C +DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning) +DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linkage has been removed + +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN + +// required includes - will go only in one translation unit! +#include +#include +#include +// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37 +#ifdef __BORLANDC__ +#include +#endif // __BORLANDC__ +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM +#include +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM +#include +#include +#include +#ifndef DOCTEST_CONFIG_NO_MULTITHREADING +#include +#include +#define DOCTEST_DECLARE_MUTEX(name) std::mutex name; +#define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name) +#define DOCTEST_LOCK_MUTEX(name) std::lock_guard DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name); +#else // DOCTEST_CONFIG_NO_MULTITHREADING +#define DOCTEST_DECLARE_MUTEX(name) +#define DOCTEST_DECLARE_STATIC_MUTEX(name) +#define DOCTEST_LOCK_MUTEX(name) +#endif // DOCTEST_CONFIG_NO_MULTITHREADING +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DOCTEST_PLATFORM_MAC +#include +#include +#include +#endif // DOCTEST_PLATFORM_MAC + +#ifdef DOCTEST_PLATFORM_WINDOWS + +// defines for a leaner windows.h +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#define DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN +#endif // WIN32_LEAN_AND_MEAN +#ifndef NOMINMAX +#define NOMINMAX +#define DOCTEST_UNDEF_NOMINMAX +#endif // NOMINMAX + +// not sure what AfxWin.h is for - here I do what Catch does +#ifdef __AFXDLL +#include +#else +#include +#endif +#include + +#else // DOCTEST_PLATFORM_WINDOWS + +#include +#include + +#endif // DOCTEST_PLATFORM_WINDOWS + +// this is a fix for https://github.com/doctest/doctest/issues/348 +// https://mail.gnome.org/archives/xml/2012-January/msg00000.html +#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO) +#define STDOUT_FILENO fileno(stdout) +#endif // HAVE_UNISTD_H + +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END + +// counts the number of elements in a C array +#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0])) + +#ifdef DOCTEST_CONFIG_DISABLE +#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_disabled +#else // DOCTEST_CONFIG_DISABLE +#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_not_disabled +#endif // DOCTEST_CONFIG_DISABLE + +#ifndef DOCTEST_CONFIG_OPTIONS_PREFIX +#define DOCTEST_CONFIG_OPTIONS_PREFIX "dt-" +#endif + +#ifndef DOCTEST_THREAD_LOCAL +#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_THREAD_LOCAL +#else // DOCTEST_MSVC +#define DOCTEST_THREAD_LOCAL thread_local +#endif // DOCTEST_MSVC +#endif // DOCTEST_THREAD_LOCAL + +#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES +#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32 +#endif + +#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE +#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64 +#endif + +#ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS +#define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX +#else +#define DOCTEST_OPTIONS_PREFIX_DISPLAY "" +#endif + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS +#endif + +#ifndef DOCTEST_CDECL +#define DOCTEST_CDECL __cdecl +#endif + +namespace doctest { + +bool is_running_in_test = false; + +namespace { + using namespace detail; + + template + DOCTEST_NORETURN void throw_exception(Ex const& e) { +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + throw e; +#else // DOCTEST_CONFIG_NO_EXCEPTIONS +#ifdef DOCTEST_CONFIG_HANDLE_EXCEPTION + DOCTEST_CONFIG_HANDLE_EXCEPTION(e); +#else // DOCTEST_CONFIG_HANDLE_EXCEPTION +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + std::cerr << "doctest will terminate because it needed to throw an exception.\n" + << "The message was: " << e.what() << '\n'; +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM +#endif // DOCTEST_CONFIG_HANDLE_EXCEPTION + std::terminate(); +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + } + +#ifndef DOCTEST_INTERNAL_ERROR +#define DOCTEST_INTERNAL_ERROR(msg) \ + throw_exception(std::logic_error( \ + __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) +#endif // DOCTEST_INTERNAL_ERROR + + // case insensitive strcmp + int stricmp(const char* a, const char* b) { + for(;; a++, b++) { + const int d = tolower(*a) - tolower(*b); + if(d != 0 || !*a) + return d; + } + } + + struct Endianness + { + enum Arch + { + Big, + Little + }; + + static Arch which() { + int x = 1; + // casting any data pointer to char* is allowed + auto ptr = reinterpret_cast(&x); + if(*ptr) + return Little; + return Big; + } + }; +} // namespace + +namespace detail { + DOCTEST_THREAD_LOCAL class + { + std::vector stack; + std::stringstream ss; + + public: + std::ostream* push() { + stack.push_back(ss.tellp()); + return &ss; + } + + String pop() { + if (stack.empty()) + DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!"); + + std::streampos pos = stack.back(); + stack.pop_back(); + unsigned sz = static_cast(ss.tellp() - pos); + ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); + return String(ss, sz); + } + } g_oss; + + std::ostream* tlssPush() { + return g_oss.push(); + } + + String tlssPop() { + return g_oss.pop(); + } + +#ifndef DOCTEST_CONFIG_DISABLE + +namespace timer_large_integer +{ + +#if defined(DOCTEST_PLATFORM_WINDOWS) + using type = ULONGLONG; +#else // DOCTEST_PLATFORM_WINDOWS + using type = std::uint64_t; +#endif // DOCTEST_PLATFORM_WINDOWS +} + +using ticks_t = timer_large_integer::type; + +#ifdef DOCTEST_CONFIG_GETCURRENTTICKS + ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); } +#elif defined(DOCTEST_PLATFORM_WINDOWS) + ticks_t getCurrentTicks() { + static LARGE_INTEGER hz = { {0} }, hzo = { {0} }; + if(!hz.QuadPart) { + QueryPerformanceFrequency(&hz); + QueryPerformanceCounter(&hzo); + } + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart; + } +#else // DOCTEST_PLATFORM_WINDOWS + ticks_t getCurrentTicks() { + timeval t; + gettimeofday(&t, nullptr); + return static_cast(t.tv_sec) * 1000000 + static_cast(t.tv_usec); + } +#endif // DOCTEST_PLATFORM_WINDOWS + + struct Timer + { + void start() { m_ticks = getCurrentTicks(); } + unsigned int getElapsedMicroseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + //unsigned int getElapsedMilliseconds() const { + // return static_cast(getElapsedMicroseconds() / 1000); + //} + double getElapsedSeconds() const { return static_cast(getCurrentTicks() - m_ticks) / 1000000.0; } + + private: + ticks_t m_ticks = 0; + }; + +#ifdef DOCTEST_CONFIG_NO_MULTITHREADING + template + using Atomic = T; +#else // DOCTEST_CONFIG_NO_MULTITHREADING + template + using Atomic = std::atomic; +#endif // DOCTEST_CONFIG_NO_MULTITHREADING + +#if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || defined(DOCTEST_CONFIG_NO_MULTITHREADING) + template + using MultiLaneAtomic = Atomic; +#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + // Provides a multilane implementation of an atomic variable that supports add, sub, load, + // store. Instead of using a single atomic variable, this splits up into multiple ones, + // each sitting on a separate cache line. The goal is to provide a speedup when most + // operations are modifying. It achieves this with two properties: + // + // * Multiple atomics are used, so chance of congestion from the same atomic is reduced. + // * Each atomic sits on a separate cache line, so false sharing is reduced. + // + // The disadvantage is that there is a small overhead due to the use of TLS, and load/store + // is slower because all atomics have to be accessed. + template + class MultiLaneAtomic + { + struct CacheLineAlignedAtomic + { + Atomic atomic{}; + char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic)]; + }; + CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES]; + + static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE, + "guarantee one atomic takes exactly one cache line"); + + public: + T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } + + T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } + + T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + return myAtomic().fetch_add(arg, order); + } + + T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + return myAtomic().fetch_sub(arg, order); + } + + operator T() const DOCTEST_NOEXCEPT { return load(); } + + T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT { + auto result = T(); + for(auto const& c : m_atomics) { + result += c.atomic.load(order); + } + return result; + } + + T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this] + store(desired); + return desired; + } + + void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + // first value becomes desired", all others become 0. + for(auto& c : m_atomics) { + c.atomic.store(desired, order); + desired = {}; + } + } + + private: + // Each thread has a different atomic that it operates on. If more than NumLanes threads + // use this, some will use the same atomic. So performance will degrade a bit, but still + // everything will work. + // + // The logic here is a bit tricky. The call should be as fast as possible, so that there + // is minimal to no overhead in determining the correct atomic for the current thread. + // + // 1. A global static counter laneCounter counts continuously up. + // 2. Each successive thread will use modulo operation of that counter so it gets an atomic + // assigned in a round-robin fashion. + // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with + // little overhead. + Atomic& myAtomic() DOCTEST_NOEXCEPT { + static Atomic laneCounter; + DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = + laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; + + return m_atomics[tlsLaneIdx].atomic; + } + }; +#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + + // this holds both parameters from the command line and runtime data for tests + struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats + { + MultiLaneAtomic numAssertsCurrentTest_atomic; + MultiLaneAtomic numAssertsFailedCurrentTest_atomic; + + std::vector> filters = decltype(filters)(9); // 9 different filters + + std::vector reporters_currently_used; + + assert_handler ah = nullptr; + + Timer timer; + + std::vector stringifiedContexts; // logging from INFO() due to an exception + + // stuff for subcases + bool reachedLeaf; + std::vector subcaseStack; + std::vector nextSubcaseStack; + std::unordered_set fullyTraversedSubcases; + size_t currentSubcaseDepth; + Atomic shouldLogCurrentException; + + void resetRunData() { + numTestCases = 0; + numTestCasesPassingFilters = 0; + numTestSuitesPassingFilters = 0; + numTestCasesFailed = 0; + numAsserts = 0; + numAssertsFailed = 0; + numAssertsCurrentTest = 0; + numAssertsFailedCurrentTest = 0; + } + + void finalizeTestCaseData() { + seconds = timer.getElapsedSeconds(); + + // update the non-atomic counters + numAsserts += numAssertsCurrentTest_atomic; + numAssertsFailed += numAssertsFailedCurrentTest_atomic; + numAssertsCurrentTest = numAssertsCurrentTest_atomic; + numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic; + + if(numAssertsFailedCurrentTest) + failure_flags |= TestCaseFailureReason::AssertFailure; + + if(Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 && + Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout) + failure_flags |= TestCaseFailureReason::Timeout; + + if(currentTest->m_should_fail) { + if(failure_flags) { + failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid; + } else { + failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt; + } + } else if(failure_flags && currentTest->m_may_fail) { + failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid; + } else if(currentTest->m_expected_failures > 0) { + if(numAssertsFailedCurrentTest == currentTest->m_expected_failures) { + failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes; + } else { + failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes; + } + } + + bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) || + (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) || + (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags); + + // if any subcase has failed - the whole test case has failed + testCaseSuccess = !(failure_flags && !ok_to_fail); + if(!testCaseSuccess) + numTestCasesFailed++; + } + }; + + ContextState* g_cs = nullptr; + + // used to avoid locks for the debug output + // TODO: figure out if this is indeed necessary/correct - seems like either there still + // could be a race or that there wouldn't be a race even if using the context directly + DOCTEST_THREAD_LOCAL bool g_no_colors; + +#endif // DOCTEST_CONFIG_DISABLE +} // namespace detail + +char* String::allocate(size_type sz) { + if (sz <= last) { + buf[sz] = '\0'; + setLast(last - sz); + return buf; + } else { + setOnHeap(); + data.size = sz; + data.capacity = data.size + 1; + data.ptr = new char[data.capacity]; + data.ptr[sz] = '\0'; + return data.ptr; + } +} + +void String::setOnHeap() noexcept { *reinterpret_cast(&buf[last]) = 128; } +void String::setLast(size_type in) noexcept { buf[last] = char(in); } +void String::setSize(size_type sz) noexcept { + if (isOnStack()) { buf[sz] = '\0'; setLast(last - sz); } + else { data.ptr[sz] = '\0'; data.size = sz; } +} + +void String::copy(const String& other) { + if(other.isOnStack()) { + memcpy(buf, other.buf, len); + } else { + memcpy(allocate(other.data.size), other.data.ptr, other.data.size); + } +} + +String::String() noexcept { + buf[0] = '\0'; + setLast(); +} + +String::~String() { + if(!isOnStack()) + delete[] data.ptr; +} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + +String::String(const char* in) + : String(in, strlen(in)) {} + +String::String(const char* in, size_type in_size) { + memcpy(allocate(in_size), in, in_size); +} + +String::String(std::istream& in, size_type in_size) { + in.read(allocate(in_size), in_size); +} + +String::String(const String& other) { copy(other); } + +String& String::operator=(const String& other) { + if(this != &other) { + if(!isOnStack()) + delete[] data.ptr; + + copy(other); + } + + return *this; +} + +String& String::operator+=(const String& other) { + const size_type my_old_size = size(); + const size_type other_size = other.size(); + const size_type total_size = my_old_size + other_size; + if(isOnStack()) { + if(total_size < len) { + // append to the current stack space + memcpy(buf + my_old_size, other.c_str(), other_size + 1); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) + setLast(last - total_size); + } else { + // alloc new chunk + char* temp = new char[total_size + 1]; + // copy current data to new location before writing in the union + memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed + // update data in union + setOnHeap(); + data.size = total_size; + data.capacity = data.size + 1; + data.ptr = temp; + // transfer the rest of the data + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + } else { + if(data.capacity > total_size) { + // append to the current heap block + data.size = total_size; + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } else { + // resize + data.capacity *= 2; + if(data.capacity <= total_size) + data.capacity = total_size + 1; + // alloc new chunk + char* temp = new char[data.capacity]; + // copy current data to new location before releasing it + memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed + // release old chunk + delete[] data.ptr; + // update the rest of the union members + data.size = total_size; + data.ptr = temp; + // transfer the rest of the data + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + } + + return *this; +} + +String::String(String&& other) noexcept { + memcpy(buf, other.buf, len); + other.buf[0] = '\0'; + other.setLast(); +} + +String& String::operator=(String&& other) noexcept { + if(this != &other) { + if(!isOnStack()) + delete[] data.ptr; + memcpy(buf, other.buf, len); + other.buf[0] = '\0'; + other.setLast(); + } + return *this; +} + +char String::operator[](size_type i) const { + return const_cast(this)->operator[](i); +} + +char& String::operator[](size_type i) { + if(isOnStack()) + return reinterpret_cast(buf)[i]; + return data.ptr[i]; +} + +DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized") +String::size_type String::size() const { + if(isOnStack()) + return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32 + return data.size; +} +DOCTEST_GCC_SUPPRESS_WARNING_POP + +String::size_type String::capacity() const { + if(isOnStack()) + return len; + return data.capacity; +} + +String String::substr(size_type pos, size_type cnt) && { + cnt = std::min(cnt, size() - 1 - pos); + char* cptr = c_str(); + memmove(cptr, cptr + pos, cnt); + setSize(cnt); + return std::move(*this); +} + +String String::substr(size_type pos, size_type cnt) const & { + cnt = std::min(cnt, size() - 1 - pos); + return String{ c_str() + pos, cnt }; +} + +String::size_type String::find(char ch, size_type pos) const { + const char* begin = c_str(); + const char* end = begin + size(); + const char* it = begin + pos; + for (; it < end && *it != ch; it++); + if (it < end) { return static_cast(it - begin); } + else { return npos; } +} + +String::size_type String::rfind(char ch, size_type pos) const { + const char* begin = c_str(); + const char* it = begin + std::min(pos, size() - 1); + for (; it >= begin && *it != ch; it--); + if (it >= begin) { return static_cast(it - begin); } + else { return npos; } +} + +int String::compare(const char* other, bool no_case) const { + if(no_case) + return doctest::stricmp(c_str(), other); + return std::strcmp(c_str(), other); +} + +int String::compare(const String& other, bool no_case) const { + return compare(other.c_str(), no_case); +} + +String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; } + +bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; } +bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; } +bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } +bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } +bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; } +bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; } + +std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); } + +Contains::Contains(const String& str) : string(str) { } + +bool Contains::checkWith(const String& other) const { + return strstr(other.c_str(), string.c_str()) != nullptr; +} + +String toString(const Contains& in) { + return "Contains( " + in.string + " )"; +} + +bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); } +bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); } +bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); } +bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); } + +namespace { + void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) +} // namespace + +namespace Color { + std::ostream& operator<<(std::ostream& s, Color::Enum code) { + color_to_stream(s, code); + return s; + } +} // namespace Color + +// clang-format off +const char* assertString(assertType::Enum at) { + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitly handled + #define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type + #define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \ + DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \ + DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK_ ## assert_type); \ + DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE_ ## assert_type) + switch(at) { + DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN); + DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK); + DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(FALSE); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_AS); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH_AS); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOTHROW); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(EQ); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(NE); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(GT); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(LT); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(GE); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(LE); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE); + + default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!"); + } + DOCTEST_MSVC_SUPPRESS_WARNING_POP +} +// clang-format on + +const char* failureString(assertType::Enum at) { + if(at & assertType::is_warn) //!OCLINT bitwise operator in conditional + return "WARNING"; + if(at & assertType::is_check) //!OCLINT bitwise operator in conditional + return "ERROR"; + if(at & assertType::is_require) //!OCLINT bitwise operator in conditional + return "FATAL ERROR"; + return ""; +} + +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") +DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") +// depending on the current options this will remove the path of filenames +const char* skipPathFromFilename(const char* file) { +#ifndef DOCTEST_CONFIG_DISABLE + if(getContextOptions()->no_path_in_filenames) { + auto back = std::strrchr(file, '\\'); + auto forward = std::strrchr(file, '/'); + if(back || forward) { + if(back > forward) + forward = back; + return forward + 1; + } + } +#endif // DOCTEST_CONFIG_DISABLE + return file; +} +DOCTEST_CLANG_SUPPRESS_WARNING_POP +DOCTEST_GCC_SUPPRESS_WARNING_POP + +bool SubcaseSignature::operator==(const SubcaseSignature& other) const { + return m_line == other.m_line + && std::strcmp(m_file, other.m_file) == 0 + && m_name == other.m_name; +} + +bool SubcaseSignature::operator<(const SubcaseSignature& other) const { + if(m_line != other.m_line) + return m_line < other.m_line; + if(std::strcmp(m_file, other.m_file) != 0) + return std::strcmp(m_file, other.m_file) < 0; + return m_name.compare(other.m_name) < 0; +} + +DOCTEST_DEFINE_INTERFACE(IContextScope) + +namespace detail { + void filldata::fill(std::ostream* stream, const void* in) { + if (in) { *stream << in; } + else { *stream << "nullptr"; } + } + + template + String toStreamLit(T t) { + std::ostream* os = tlssPush(); + os->operator<<(t); + return tlssPop(); + } +} + +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) +// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 +String toString(const std::string& in) { return in.c_str(); } +#endif // VS 2019 + +String toString(String in) { return in; } + +String toString(std::nullptr_t) { return "nullptr"; } + +String toString(bool in) { return in ? "true" : "false"; } + +String toString(float in) { return toStreamLit(in); } +String toString(double in) { return toStreamLit(in); } +String toString(double long in) { return toStreamLit(in); } + +String toString(char in) { return toStreamLit(static_cast(in)); } +String toString(char signed in) { return toStreamLit(static_cast(in)); } +String toString(char unsigned in) { return toStreamLit(static_cast(in)); } +String toString(short in) { return toStreamLit(in); } +String toString(short unsigned in) { return toStreamLit(in); } +String toString(signed in) { return toStreamLit(in); } +String toString(unsigned in) { return toStreamLit(in); } +String toString(long in) { return toStreamLit(in); } +String toString(long unsigned in) { return toStreamLit(in); } +String toString(long long in) { return toStreamLit(in); } +String toString(long long unsigned in) { return toStreamLit(in); } + +Approx::Approx(double value) + : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100) + , m_scale(1.0) + , m_value(value) {} + +Approx Approx::operator()(double value) const { + Approx approx(value); + approx.epsilon(m_epsilon); + approx.scale(m_scale); + return approx; +} + +Approx& Approx::epsilon(double newEpsilon) { + m_epsilon = newEpsilon; + return *this; +} +Approx& Approx::scale(double newScale) { + m_scale = newScale; + return *this; +} + +bool operator==(double lhs, const Approx& rhs) { + // Thanks to Richard Harris for his help refining this formula + return std::fabs(lhs - rhs.m_value) < + rhs.m_epsilon * (rhs.m_scale + std::max(std::fabs(lhs), std::fabs(rhs.m_value))); +} +bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); } +bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); } +bool operator!=(const Approx& lhs, double rhs) { return !operator==(rhs, lhs); } +bool operator<=(double lhs, const Approx& rhs) { return lhs < rhs.m_value || lhs == rhs; } +bool operator<=(const Approx& lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; } +bool operator>=(double lhs, const Approx& rhs) { return lhs > rhs.m_value || lhs == rhs; } +bool operator>=(const Approx& lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; } +bool operator<(double lhs, const Approx& rhs) { return lhs < rhs.m_value && lhs != rhs; } +bool operator<(const Approx& lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; } +bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs != rhs; } +bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; } + +String toString(const Approx& in) { + return "Approx( " + doctest::toString(in.m_value) + " )"; +} +const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } + +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) +template +IsNaN::operator bool() const { + return std::isnan(value) ^ flipped; +} +DOCTEST_MSVC_SUPPRESS_WARNING_POP +template struct DOCTEST_INTERFACE_DEF IsNaN; +template struct DOCTEST_INTERFACE_DEF IsNaN; +template struct DOCTEST_INTERFACE_DEF IsNaN; +template +String toString(IsNaN in) { return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; } +String toString(IsNaN in) { return toString(in); } +String toString(IsNaN in) { return toString(in); } +String toString(IsNaN in) { return toString(in); } + +} // namespace doctest + +#ifdef DOCTEST_CONFIG_DISABLE +namespace doctest { +Context::Context(int, const char* const*) {} +Context::~Context() = default; +void Context::applyCommandLine(int, const char* const*) {} +void Context::addFilter(const char*, const char*) {} +void Context::clearFilters() {} +void Context::setOption(const char*, bool) {} +void Context::setOption(const char*, int) {} +void Context::setOption(const char*, const char*) {} +bool Context::shouldExit() { return false; } +void Context::setAsDefaultForAssertsOutOfTestCases() {} +void Context::setAssertHandler(detail::assert_handler) {} +void Context::setCout(std::ostream*) {} +int Context::run() { return 0; } + +int IReporter::get_num_active_contexts() { return 0; } +const IContextScope* const* IReporter::get_active_contexts() { return nullptr; } +int IReporter::get_num_stringified_contexts() { return 0; } +const String* IReporter::get_stringified_contexts() { return nullptr; } + +int registerReporter(const char*, int, IReporter*) { return 0; } + +} // namespace doctest +#else // DOCTEST_CONFIG_DISABLE + +#if !defined(DOCTEST_CONFIG_COLORS_NONE) +#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI) +#ifdef DOCTEST_PLATFORM_WINDOWS +#define DOCTEST_CONFIG_COLORS_WINDOWS +#else // linux +#define DOCTEST_CONFIG_COLORS_ANSI +#endif // platform +#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI +#endif // DOCTEST_CONFIG_COLORS_NONE + +namespace doctest_detail_test_suite_ns { +// holds the current test suite +doctest::detail::TestSuite& getCurrentTestSuite() { + static doctest::detail::TestSuite data{}; + return data; +} +} // namespace doctest_detail_test_suite_ns + +namespace doctest { +namespace { + // the int (priority) is part of the key for automatic sorting - sadly one can register a + // reporter with a duplicate name and a different priority but hopefully that won't happen often :| + using reporterMap = std::map, reporterCreatorFunc>; + + reporterMap& getReporters() { + static reporterMap data; + return data; + } + reporterMap& getListeners() { + static reporterMap data; + return data; + } +} // namespace +namespace detail { +#define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \ + for(auto& curr_rep : g_cs->reporters_currently_used) \ + curr_rep->function(__VA_ARGS__) + + bool checkIfShouldThrow(assertType::Enum at) { + if(at & assertType::is_require) //!OCLINT bitwise operator in conditional + return true; + + if((at & assertType::is_check) //!OCLINT bitwise operator in conditional + && getContextOptions()->abort_after > 0 && + (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >= + getContextOptions()->abort_after) + return true; + + return false; + } + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + DOCTEST_NORETURN void throwException() { + g_cs->shouldLogCurrentException = false; + throw TestFailureException(); // NOLINT(hicpp-exception-baseclass) + } +#else // DOCTEST_CONFIG_NO_EXCEPTIONS + void throwException() {} +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS +} // namespace detail + +namespace { + using namespace detail; + // matching of a string against a wildcard mask (case sensitivity configurable) taken from + // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing + int wildcmp(const char* str, const char* wild, bool caseSensitive) { + const char* cp = str; + const char* mp = wild; + + while((*str) && (*wild != '*')) { + if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && + (*wild != '?')) { + return 0; + } + wild++; + str++; + } + + while(*str) { + if(*wild == '*') { + if(!*++wild) { + return 1; + } + mp = wild; + cp = str + 1; + } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) || + (*wild == '?')) { + wild++; + str++; + } else { + wild = mp; //!OCLINT parameter reassignment + str = cp++; //!OCLINT parameter reassignment + } + } + + while(*wild == '*') { + wild++; + } + return !*wild; + } + + // checks if the name matches any of the filters (and can be configured what to do when empty) + bool matchesAny(const char* name, const std::vector& filters, bool matchEmpty, + bool caseSensitive) { + if (filters.empty() && matchEmpty) + return true; + for (auto& curr : filters) + if (wildcmp(name, curr.c_str(), caseSensitive)) + return true; + return false; + } + + DOCTEST_NO_SANITIZE_INTEGER + unsigned long long hash(unsigned long long a, unsigned long long b) { + return (a << 5) + b; + } + + // C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html + DOCTEST_NO_SANITIZE_INTEGER + unsigned long long hash(const char* str) { + unsigned long long hash = 5381; + char c; + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; // hash * 33 + c + return hash; + } + + unsigned long long hash(const SubcaseSignature& sig) { + return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line); + } + + unsigned long long hash(const std::vector& sigs, size_t count) { + unsigned long long running = 0; + auto end = sigs.begin() + count; + for (auto it = sigs.begin(); it != end; it++) { + running = hash(running, hash(*it)); + } + return running; + } + + unsigned long long hash(const std::vector& sigs) { + unsigned long long running = 0; + for (const SubcaseSignature& sig : sigs) { + running = hash(running, hash(sig)); + } + return running; + } +} // namespace +namespace detail { + bool Subcase::checkFilters() { + if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) { + if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive)) + return true; + if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive)) + return true; + } + return false; + } + + Subcase::Subcase(const String& name, const char* file, int line) + : m_signature({name, file, line}) { + if (!g_cs->reachedLeaf) { + if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size() + || g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) { + // Going down. + if (checkFilters()) { return; } + + g_cs->subcaseStack.push_back(m_signature); + g_cs->currentSubcaseDepth++; + m_entered = true; + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); + } + } else { + if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) { + // This subcase is reentered via control flow. + g_cs->currentSubcaseDepth++; + m_entered = true; + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); + } else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth + && g_cs->fullyTraversedSubcases.find(hash(hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature))) + == g_cs->fullyTraversedSubcases.end()) { + if (checkFilters()) { return; } + // This subcase is part of the one to be executed next. + g_cs->nextSubcaseStack.clear(); + g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(), + g_cs->subcaseStack.begin(), g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth); + g_cs->nextSubcaseStack.push_back(m_signature); + } + } + } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + + Subcase::~Subcase() { + if (m_entered) { + g_cs->currentSubcaseDepth--; + + if (!g_cs->reachedLeaf) { + // Leaf. + g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); + g_cs->nextSubcaseStack.clear(); + g_cs->reachedLeaf = true; + } else if (g_cs->nextSubcaseStack.empty()) { + // All children are finished. + g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); + } + +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + if(std::uncaught_exceptions() > 0 +#else + if(std::uncaught_exception() +#endif + && g_cs->shouldLogCurrentException) { + DOCTEST_ITERATE_THROUGH_REPORTERS( + test_case_exception, {"exception thrown in subcase - will translate later " + "when the whole test case has been exited (cannot " + "translate while there is an active exception)", + false}); + g_cs->shouldLogCurrentException = false; + } + + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } + } + + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + Subcase::operator bool() const { return m_entered; } + + Result::Result(bool passed, const String& decomposition) + : m_passed(passed) + , m_decomp(decomposition) {} + + ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) + : m_at(at) {} + + TestSuite& TestSuite::operator*(const char* in) { + m_test_suite = in; + return *this; + } + + TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, + const String& type, int template_id) { + m_file = file; + m_line = line; + m_name = nullptr; // will be later overridden in operator* + m_test_suite = test_suite.m_test_suite; + m_description = test_suite.m_description; + m_skip = test_suite.m_skip; + m_no_breaks = test_suite.m_no_breaks; + m_no_output = test_suite.m_no_output; + m_may_fail = test_suite.m_may_fail; + m_should_fail = test_suite.m_should_fail; + m_expected_failures = test_suite.m_expected_failures; + m_timeout = test_suite.m_timeout; + + m_test = test; + m_type = type; + m_template_id = template_id; + } + + TestCase::TestCase(const TestCase& other) + : TestCaseData() { + *this = other; + } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function + TestCase& TestCase::operator=(const TestCase& other) { + TestCaseData::operator=(other); + m_test = other.m_test; + m_type = other.m_type; + m_template_id = other.m_template_id; + m_full_name = other.m_full_name; + + if(m_template_id != -1) + m_name = m_full_name.c_str(); + return *this; + } + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + TestCase& TestCase::operator*(const char* in) { + m_name = in; + // make a new name with an appended type for templated test case + if(m_template_id != -1) { + m_full_name = String(m_name) + "<" + m_type + ">"; + // redirect the name to point to the newly constructed full name + m_name = m_full_name.c_str(); + } + return *this; + } + + bool TestCase::operator<(const TestCase& other) const { + // this will be used only to differentiate between test cases - not relevant for sorting + if(m_line != other.m_line) + return m_line < other.m_line; + const int name_cmp = strcmp(m_name, other.m_name); + if(name_cmp != 0) + return name_cmp < 0; + const int file_cmp = m_file.compare(other.m_file); + if(file_cmp != 0) + return file_cmp < 0; + return m_template_id < other.m_template_id; + } + + // all the registered tests + std::set& getRegisteredTests() { + static std::set data; + return data; + } +} // namespace detail +namespace { + using namespace detail; + // for sorting tests by file/line + bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) { + // this is needed because MSVC gives different case for drive letters + // for __FILE__ when evaluated in a header and a source file + const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC)); + if(res != 0) + return res < 0; + if(lhs->m_line != rhs->m_line) + return lhs->m_line < rhs->m_line; + return lhs->m_template_id < rhs->m_template_id; + } + + // for sorting tests by suite/file/line + bool suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) { + const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite); + if(res != 0) + return res < 0; + return fileOrderComparator(lhs, rhs); + } + + // for sorting tests by name/suite/file/line + bool nameOrderComparator(const TestCase* lhs, const TestCase* rhs) { + const int res = std::strcmp(lhs->m_name, rhs->m_name); + if(res != 0) + return res < 0; + return suiteOrderComparator(lhs, rhs); + } + + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + void color_to_stream(std::ostream& s, Color::Enum code) { + static_cast(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS + static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE +#ifdef DOCTEST_CONFIG_COLORS_ANSI + if(g_no_colors || + (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false)) + return; + + auto col = ""; + // clang-format off + switch(code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement + case Color::Red: col = "[0;31m"; break; + case Color::Green: col = "[0;32m"; break; + case Color::Blue: col = "[0;34m"; break; + case Color::Cyan: col = "[0;36m"; break; + case Color::Yellow: col = "[0;33m"; break; + case Color::Grey: col = "[1;30m"; break; + case Color::LightGrey: col = "[0;37m"; break; + case Color::BrightRed: col = "[1;31m"; break; + case Color::BrightGreen: col = "[1;32m"; break; + case Color::BrightWhite: col = "[1;37m"; break; + case Color::Bright: // invalid + case Color::None: + case Color::White: + default: col = "[0m"; + } + // clang-format on + s << "\033" << col; +#endif // DOCTEST_CONFIG_COLORS_ANSI + +#ifdef DOCTEST_CONFIG_COLORS_WINDOWS + if(g_no_colors || + (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false)) + return; + + static struct ConsoleHelper { + HANDLE stdoutHandle; + WORD origFgAttrs; + WORD origBgAttrs; + + ConsoleHelper() { + stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); + origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | + BACKGROUND_BLUE | BACKGROUND_INTENSITY); + origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_BLUE | FOREGROUND_INTENSITY); + } + } ch; + +#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs) + + // clang-format off + switch (code) { + case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; + case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break; + case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break; + case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break; + case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break; + case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break; + case Color::Grey: DOCTEST_SET_ATTR(0); break; + case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break; + case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break; + case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break; + case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; + case Color::None: + case Color::Bright: // invalid + default: DOCTEST_SET_ATTR(ch.origFgAttrs); + } + // clang-format on +#endif // DOCTEST_CONFIG_COLORS_WINDOWS + } + DOCTEST_CLANG_SUPPRESS_WARNING_POP + + std::vector& getExceptionTranslators() { + static std::vector data; + return data; + } + + String translateActiveException() { +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + String res; + auto& translators = getExceptionTranslators(); + for(auto& curr : translators) + if(curr->translate(res)) + return res; + // clang-format off + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value") + try { + throw; + } catch(std::exception& ex) { + return ex.what(); + } catch(std::string& msg) { + return msg.c_str(); + } catch(const char* msg) { + return msg; + } catch(...) { + return "unknown exception"; + } + DOCTEST_GCC_SUPPRESS_WARNING_POP +// clang-format on +#else // DOCTEST_CONFIG_NO_EXCEPTIONS + return ""; +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + } +} // namespace + +namespace detail { + // used by the macros for registering tests + int regTest(const TestCase& tc) { + getRegisteredTests().insert(tc); + return 0; + } + + // sets the current test suite + int setTestSuite(const TestSuite& ts) { + doctest_detail_test_suite_ns::getCurrentTestSuite() = ts; + return 0; + } + +#ifdef DOCTEST_IS_DEBUGGER_ACTIVE + bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); } +#else // DOCTEST_IS_DEBUGGER_ACTIVE +#ifdef DOCTEST_PLATFORM_LINUX + class ErrnoGuard { + public: + ErrnoGuard() : m_oldErrno(errno) {} + ~ErrnoGuard() { errno = m_oldErrno; } + private: + int m_oldErrno; + }; + // See the comments in Catch2 for the reasoning behind this implementation: + // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102 + bool isDebuggerActive() { + ErrnoGuard guard; + std::ifstream in("/proc/self/status"); + for(std::string line; std::getline(in, line);) { + static const int PREFIX_LEN = 11; + if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + return false; + } +#elif defined(DOCTEST_PLATFORM_MAC) + // The following function is taken directly from the following technical note: + // https://developer.apple.com/library/archive/qa/qa1361/_index.html + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive() { + int mib[4]; + kinfo_proc info; + size_t size; + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + info.kp_proc.p_flag = 0; + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + // Call sysctl. + size = sizeof(info); + if(sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) { + std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n"; + return false; + } + // We're being debugged if the P_TRACED flag is set. + return ((info.kp_proc.p_flag & P_TRACED) != 0); + } +#elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__) + bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; } +#else + bool isDebuggerActive() { return false; } +#endif // Platform +#endif // DOCTEST_IS_DEBUGGER_ACTIVE + + void registerExceptionTranslatorImpl(const IExceptionTranslator* et) { + if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) == + getExceptionTranslators().end()) + getExceptionTranslators().push_back(et); + } + + DOCTEST_THREAD_LOCAL std::vector g_infoContexts; // for logging with INFO() + + ContextScopeBase::ContextScopeBase() { + g_infoContexts.push_back(this); + } + + ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept { + if (other.need_to_destroy) { + other.destroy(); + } + other.need_to_destroy = false; + g_infoContexts.push_back(this); + } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + + // destroy cannot be inlined into the destructor because that would mean calling stringify after + // ContextScope has been destroyed (base class destructors run after derived class destructors). + // Instead, ContextScope calls this method directly from its destructor. + void ContextScopeBase::destroy() { +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + if(std::uncaught_exceptions() > 0) { +#else + if(std::uncaught_exception()) { +#endif + std::ostringstream s; + this->stringify(&s); + g_cs->stringifiedContexts.push_back(s.str().c_str()); + } + g_infoContexts.pop_back(); + } + + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP +} // namespace detail +namespace { + using namespace detail; + +#if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) + struct FatalConditionHandler + { + static void reset() {} + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + }; +#else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH + + void reportFatal(const std::string&); + +#ifdef DOCTEST_PLATFORM_WINDOWS + + struct SignalDefs + { + DWORD id; + const char* name; + }; + // There is no 1-1 mapping between signals and windows exceptions. + // Windows can easily distinguish between SO and SigSegV, + // but SigInt, SigTerm, etc are handled differently. + SignalDefs signalDefs[] = { + {static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), + "SIGILL - Illegal instruction signal"}, + {static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, + {static_cast(EXCEPTION_ACCESS_VIOLATION), + "SIGSEGV - Segmentation violation signal"}, + {static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, + }; + + struct FatalConditionHandler + { + static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) { + // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the + // console just once no matter how many threads have crashed. + DOCTEST_DECLARE_STATIC_MUTEX(mutex) + static bool execute = true; + { + DOCTEST_LOCK_MUTEX(mutex) + if(execute) { + bool reported = false; + for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + reported = true; + break; + } + } + if(reported == false) + reportFatal("Unhandled SEH exception caught"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + } + execute = false; + } + std::exit(EXIT_FAILURE); + } + + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + + FatalConditionHandler() { + isSet = true; + // 32k seems enough for doctest to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + // Register an unhandled exception filter + previousTop = SetUnhandledExceptionFilter(handleException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); + + // On Windows uncaught exceptions from another thread, exceptions from + // destructors, or calls to std::terminate are not a SEH exception + + // The terminal handler gets called when: + // - std::terminate is called FROM THE TEST RUNNER THREAD + // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD + original_terminate_handler = std::get_terminate(); + std::set_terminate([]() DOCTEST_NOEXCEPT { + reportFatal("Terminate handler called"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well + }); + + // SIGABRT is raised when: + // - std::terminate is called FROM A DIFFERENT THREAD + // - an exception is thrown from a destructor FROM A DIFFERENT THREAD + // - an uncaught exception is thrown FROM A DIFFERENT THREAD + prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { + if(signal == SIGABRT) { + reportFatal("SIGABRT - Abort (abnormal termination) signal"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); + } + }); + + // The following settings are taken from google test, and more + // specifically from UnitTest::Run() inside of gtest.cc + + // the user does not want to see pop-up dialogs about crashes + prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + // This forces the abort message to go to stderr in all circumstances. + prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program - we want to disable that. + prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + // In debug mode, the Windows CRT can crash with an assertion over invalid + // input (e.g. passing an invalid file descriptor). The default handling + // for these assertions is to pop up a dialog and wait for user input. + // Instead ask the CRT to dump such assertions to stderr non-interactively. + prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + } + + static void reset() { + if(isSet) { + // Unregister handler and restore the old guarantee + SetUnhandledExceptionFilter(previousTop); + SetThreadStackGuarantee(&guaranteeSize); + std::set_terminate(original_terminate_handler); + std::signal(SIGABRT, prev_sigabrt_handler); + SetErrorMode(prev_error_mode_1); + _set_error_mode(prev_error_mode_2); + _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + static_cast(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode)); + static_cast(_CrtSetReportFile(_CRT_ASSERT, prev_report_file)); + isSet = false; + } + } + + ~FatalConditionHandler() { reset(); } + + private: + static UINT prev_error_mode_1; + static int prev_error_mode_2; + static unsigned int prev_abort_behavior; + static int prev_report_mode; + static _HFILE prev_report_file; + static void (DOCTEST_CDECL *prev_sigabrt_handler)(int); + static std::terminate_handler original_terminate_handler; + static bool isSet; + static ULONG guaranteeSize; + static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; + }; + + UINT FatalConditionHandler::prev_error_mode_1; + int FatalConditionHandler::prev_error_mode_2; + unsigned int FatalConditionHandler::prev_abort_behavior; + int FatalConditionHandler::prev_report_mode; + _HFILE FatalConditionHandler::prev_report_file; + void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int); + std::terminate_handler FatalConditionHandler::original_terminate_handler; + bool FatalConditionHandler::isSet = false; + ULONG FatalConditionHandler::guaranteeSize = 0; + LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; + +#else // DOCTEST_PLATFORM_WINDOWS + + struct SignalDefs + { + int id; + const char* name; + }; + SignalDefs signalDefs[] = {{SIGINT, "SIGINT - Terminal interrupt signal"}, + {SIGILL, "SIGILL - Illegal instruction signal"}, + {SIGFPE, "SIGFPE - Floating point error signal"}, + {SIGSEGV, "SIGSEGV - Segmentation violation signal"}, + {SIGTERM, "SIGTERM - Termination request signal"}, + {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}}; + + struct FatalConditionHandler + { + static bool isSet; + static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; + static stack_t oldSigStack; + static size_t altStackSize; + static char* altStackMem; + + static void handleSignal(int sig) { + const char* name = ""; + for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + SignalDefs& def = signalDefs[i]; + if(sig == def.id) { + name = def.name; + break; + } + } + reset(); + reportFatal(name); + raise(sig); + } + + static void allocateAltStackMem() { + altStackMem = new char[altStackSize]; + } + + static void freeAltStackMem() { + delete[] altStackMem; + } + + FatalConditionHandler() { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = altStackSize; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = {}; + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + ~FatalConditionHandler() { reset(); } + static void reset() { + if(isSet) { + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + isSet = false; + } + } + }; + + bool FatalConditionHandler::isSet = false; + struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ; + char* FatalConditionHandler::altStackMem = nullptr; + +#endif // DOCTEST_PLATFORM_WINDOWS +#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH + +} // namespace + +namespace { + using namespace detail; + +#ifdef DOCTEST_PLATFORM_WINDOWS +#define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text) +#else + // TODO: integration with XCode and other IDEs +#define DOCTEST_OUTPUT_DEBUG_STRING(text) +#endif // Platform + + void addAssert(assertType::Enum at) { + if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional + g_cs->numAssertsCurrentTest_atomic++; + } + + void addFailedAssert(assertType::Enum at) { + if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional + g_cs->numAssertsFailedCurrentTest_atomic++; + } + +#if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH) + void reportFatal(const std::string& message) { + g_cs->failure_flags |= TestCaseFailureReason::Crash; + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true}); + + while (g_cs->subcaseStack.size()) { + g_cs->subcaseStack.pop_back(); + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } + + g_cs->finalizeTestCaseData(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); + } +#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH +} // namespace + +AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const StringContains& exception_string) + : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr), + m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type), + m_exception_string(exception_string) { +#if DOCTEST_MSVC + if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC + ++m_expr; +#endif // MSVC +} + +namespace detail { + ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const String& exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) { } + + ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const Contains& exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) { } + + void ResultBuilder::setResult(const Result& res) { + m_decomp = res.m_decomp; + m_failed = !res.m_passed; + } + + void ResultBuilder::translateException() { + m_threw = true; + m_exception = translateActiveException(); + } + + bool ResultBuilder::log() { + if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional + m_failed = !m_threw; + } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT + m_failed = !m_threw_as || !m_exception_string.check(m_exception); + } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional + m_failed = !m_threw_as; + } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional + m_failed = !m_exception_string.check(m_exception); + } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional + m_failed = m_threw; + } + + if(m_exception.size()) + m_exception = "\"" + m_exception + "\""; + + if(is_running_in_test) { + addAssert(m_at); + DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this); + + if(m_failed) + addFailedAssert(m_at); + } else if(m_failed) { + failed_out_of_a_testing_context(*this); + } + + return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks && + (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger + } + + void ResultBuilder::react() const { + if(m_failed && checkIfShouldThrow(m_at)) + throwException(); + } + + void failed_out_of_a_testing_context(const AssertData& ad) { + if(g_cs->ah) + g_cs->ah(ad); + else + std::abort(); + } + + bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr, + const Result& result) { + bool failed = !result.m_passed; + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); + DOCTEST_ASSERT_IN_TESTS(result.m_decomp); + return !failed; + } + + MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) { + m_stream = tlssPush(); + m_file = file; + m_line = line; + m_severity = severity; + } + + MessageBuilder::~MessageBuilder() { + if (!logged) + tlssPop(); + } + + DOCTEST_DEFINE_INTERFACE(IExceptionTranslator) + + bool MessageBuilder::log() { + if (!logged) { + m_string = tlssPop(); + logged = true; + } + + DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this); + + const bool isWarn = m_severity & assertType::is_warn; + + // warn is just a message in this context so we don't treat it as an assert + if(!isWarn) { + addAssert(m_severity); + addFailedAssert(m_severity); + } + + return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn && + (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger + } + + void MessageBuilder::react() { + if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional + throwException(); + } +} // namespace detail +namespace { + using namespace detail; + + // clang-format off + +// ================================================================================================= +// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp +// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched. +// ================================================================================================= + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); + + void encodeTo( std::ostream& os ) const; + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ); + + ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT; + ScopedElement& operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT; + + ~ScopedElement(); + + ScopedElement& writeText( std::string const& text, bool indent = true ); + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer = nullptr; + }; + +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + XmlWriter( std::ostream& os = std::cout ); +#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + XmlWriter( std::ostream& os ); +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + ~XmlWriter(); + + XmlWriter( XmlWriter const& ) = delete; + XmlWriter& operator=( XmlWriter const& ) = delete; + + XmlWriter& startElement( std::string const& name ); + + ScopedElement scopedElement( std::string const& name ); + + XmlWriter& endElement(); + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); + + XmlWriter& writeAttribute( std::string const& name, const char* attribute ); + + XmlWriter& writeAttribute( std::string const& name, bool attribute ); + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + std::stringstream rss; + rss << attribute; + return writeAttribute( name, rss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ); + + //XmlWriter& writeComment( std::string const& text ); + + //void writeStylesheetRef( std::string const& url ); + + //XmlWriter& writeBlankLine(); + + void ensureTagClosed(); + + void writeDeclaration(); + + private: + + void newlineIfNecessary(); + + bool m_tagIsOpen = false; + bool m_needsNewline = false; + std::vector m_tags; + std::string m_indent; + std::ostream& m_os; + }; + +// ================================================================================================= +// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp +// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched. +// ================================================================================================= + +using uchar = unsigned char; + +namespace { + + size_t trailingBytes(unsigned char c) { + if ((c & 0xE0) == 0xC0) { + return 2; + } + if ((c & 0xF0) == 0xE0) { + return 3; + } + if ((c & 0xF8) == 0xF0) { + return 4; + } + DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); + } + + uint32_t headerValue(unsigned char c) { + if ((c & 0xE0) == 0xC0) { + return c & 0x1F; + } + if ((c & 0xF0) == 0xE0) { + return c & 0x0F; + } + if ((c & 0xF8) == 0xF0) { + return c & 0x07; + } + DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); + } + + void hexEscapeChar(std::ostream& os, unsigned char c) { + std::ios_base::fmtflags f(os.flags()); + os << "\\x" + << std::uppercase << std::hex << std::setfill('0') << std::setw(2) + << static_cast(c); + os.flags(f); + } + +} // anonymous namespace + + XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void XmlEncode::encodeTo( std::ostream& os ) const { + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: https://www.w3.org/TR/xml/#syntax) + + for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { + uchar c = m_str[idx]; + switch (c) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: https://www.w3.org/TR/xml/#syntax + if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') + os << ">"; + else + os << c; + break; + + case '\"': + if (m_forWhat == ForAttributes) + os << """; + else + os << c; + break; + + default: + // Check for control characters and invalid utf-8 + + // Escape control characters in standard ascii + // see https://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { + hexEscapeChar(os, c); + break; + } + + // Plain ASCII: Write it to stream + if (c < 0x7F) { + os << c; + break; + } + + // UTF-8 territory + // Check if the encoding is valid and if it is not, hex escape bytes. + // Important: We do not check the exact decoded values for validity, only the encoding format + // First check that this bytes is a valid lead byte: + // This means that it is not encoded as 1111 1XXX + // Or as 10XX XXXX + if (c < 0xC0 || + c >= 0xF8) { + hexEscapeChar(os, c); + break; + } + + auto encBytes = trailingBytes(c); + // Are there enough bytes left to avoid accessing out-of-bounds memory? + if (idx + encBytes - 1 >= m_str.size()) { + hexEscapeChar(os, c); + break; + } + // The header is valid, check data + // The next encBytes bytes must together be a valid utf-8 + // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) + bool valid = true; + uint32_t value = headerValue(c); + for (std::size_t n = 1; n < encBytes; ++n) { + uchar nc = m_str[idx + n]; + valid &= ((nc & 0xC0) == 0x80); + value = (value << 6) | (nc & 0x3F); + } + + if ( + // Wrong bit pattern of following bytes + (!valid) || + // Overlong encodings + (value < 0x80) || + ( value < 0x800 && encBytes > 2) || // removed "0x80 <= value &&" because redundant + (0x800 < value && value < 0x10000 && encBytes > 3) || + // Encoded value out of range + (value >= 0x110000) + ) { + hexEscapeChar(os, c); + break; + } + + // If we got here, this is in fact a valid(ish) utf-8 sequence + for (std::size_t n = 0; n < encBytes; ++n) { + os << m_str[idx + n]; + } + idx += encBytes - 1; + break; + } + } + } + + std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT + : m_writer( other.m_writer ){ + other.m_writer = nullptr; + } + XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT { + if ( m_writer ) { + m_writer->endElement(); + } + m_writer = other.m_writer; + other.m_writer = nullptr; + return *this; + } + + + XmlWriter::ScopedElement::~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { + m_writer->writeText( text, indent ); + return *this; + } + + XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) + { + // writeDeclaration(); // called explicitly by the reporters that use the writer class - see issue #627 + } + + XmlWriter::~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& XmlWriter::startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + m_os << m_indent << '<' << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& XmlWriter::endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + m_os << "/>"; + m_tagIsOpen = false; + } + else { + m_os << m_indent << ""; + } + m_os << std::endl; + m_tags.pop_back(); + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, const char* attribute ) { + if( !name.empty() && attribute && attribute[0] != '\0' ) + m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { + m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + m_os << m_indent; + m_os << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + //XmlWriter& XmlWriter::writeComment( std::string const& text ) { + // ensureTagClosed(); + // m_os << m_indent << ""; + // m_needsNewline = true; + // return *this; + //} + + //void XmlWriter::writeStylesheetRef( std::string const& url ) { + // m_os << "\n"; + //} + + //XmlWriter& XmlWriter::writeBlankLine() { + // ensureTagClosed(); + // m_os << '\n'; + // return *this; + //} + + void XmlWriter::ensureTagClosed() { + if( m_tagIsOpen ) { + m_os << ">" << std::endl; + m_tagIsOpen = false; + } + } + + void XmlWriter::writeDeclaration() { + m_os << "\n"; + } + + void XmlWriter::newlineIfNecessary() { + if( m_needsNewline ) { + m_os << std::endl; + m_needsNewline = false; + } + } + +// ================================================================================================= +// End of copy-pasted code from Catch +// ================================================================================================= + + // clang-format on + + struct XmlReporter : public IReporter + { + XmlWriter xml; + DOCTEST_DECLARE_MUTEX(mutex) + + // caching pointers/references to objects of these types - safe to do + const ContextOptions& opt; + const TestCaseData* tc = nullptr; + + XmlReporter(const ContextOptions& co) + : xml(*co.cout) + , opt(co) {} + + void log_contexts() { + int num_contexts = get_num_active_contexts(); + if(num_contexts) { + auto contexts = get_active_contexts(); + std::stringstream ss; + for(int i = 0; i < num_contexts; ++i) { + contexts[i]->stringify(&ss); + xml.scopedElement("Info").writeText(ss.str()); + ss.str(""); + } + } + } + + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } + + void test_case_start_impl(const TestCaseData& in) { + bool open_ts_tag = false; + if(tc != nullptr) { // we have already opened a test suite + if(std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) { + xml.endElement(); + open_ts_tag = true; + } + } + else { + open_ts_tag = true; // first test case ==> first test suite + } + + if(open_ts_tag) { + xml.startElement("TestSuite"); + xml.writeAttribute("name", in.m_test_suite); + } + + tc = ∈ + xml.startElement("TestCase") + .writeAttribute("name", in.m_name) + .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str())) + .writeAttribute("line", line(in.m_line)) + .writeAttribute("description", in.m_description); + + if(Approx(in.m_timeout) != 0) + xml.writeAttribute("timeout", in.m_timeout); + if(in.m_may_fail) + xml.writeAttribute("may_fail", true); + if(in.m_should_fail) + xml.writeAttribute("should_fail", true); + } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData& in) override { + test_run_start(); + if(opt.list_reporters) { + for(auto& curr : getListeners()) + xml.scopedElement("Listener") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); + for(auto& curr : getReporters()) + xml.scopedElement("Reporter") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); + } else if(opt.count || opt.list_test_cases) { + for(unsigned i = 0; i < in.num_data; ++i) { + xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name) + .writeAttribute("testsuite", in.data[i]->m_test_suite) + .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str())) + .writeAttribute("line", line(in.data[i]->m_line)) + .writeAttribute("skipped", in.data[i]->m_skip); + } + xml.scopedElement("OverallResultsTestCases") + .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); + } else if(opt.list_test_suites) { + for(unsigned i = 0; i < in.num_data; ++i) + xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite); + xml.scopedElement("OverallResultsTestCases") + .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); + xml.scopedElement("OverallResultsTestSuites") + .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters); + } + xml.endElement(); + } + + void test_run_start() override { + xml.writeDeclaration(); + + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); +#ifdef DOCTEST_PLATFORM_WINDOWS + if(binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); +#endif // DOCTEST_PLATFORM_WINDOWS + + xml.startElement("doctest").writeAttribute("binary", binary_name); + if(opt.no_version == false) + xml.writeAttribute("version", DOCTEST_VERSION_STR); + + // only the consequential ones (TODO: filters) + xml.scopedElement("Options") + .writeAttribute("order_by", opt.order_by.c_str()) + .writeAttribute("rand_seed", opt.rand_seed) + .writeAttribute("first", opt.first) + .writeAttribute("last", opt.last) + .writeAttribute("abort_after", opt.abort_after) + .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels) + .writeAttribute("case_sensitive", opt.case_sensitive) + .writeAttribute("no_throw", opt.no_throw) + .writeAttribute("no_skip", opt.no_skip); + } + + void test_run_end(const TestRunStats& p) override { + if(tc) // the TestSuite tag - only if there has been at least 1 test case + xml.endElement(); + + xml.scopedElement("OverallResultsAsserts") + .writeAttribute("successes", p.numAsserts - p.numAssertsFailed) + .writeAttribute("failures", p.numAssertsFailed); + + xml.startElement("OverallResultsTestCases") + .writeAttribute("successes", + p.numTestCasesPassingFilters - p.numTestCasesFailed) + .writeAttribute("failures", p.numTestCasesFailed); + if(opt.no_skipped_summary == false) + xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters); + xml.endElement(); + + xml.endElement(); + } + + void test_case_start(const TestCaseData& in) override { + test_case_start_impl(in); + xml.ensureTagClosed(); + } + + void test_case_reenter(const TestCaseData&) override {} + + void test_case_end(const CurrentTestCaseStats& st) override { + xml.startElement("OverallResultsAsserts") + .writeAttribute("successes", + st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest) + .writeAttribute("failures", st.numAssertsFailedCurrentTest) + .writeAttribute("test_case_success", st.testCaseSuccess); + if(opt.duration) + xml.writeAttribute("duration", st.seconds); + if(tc->m_expected_failures) + xml.writeAttribute("expected_failures", tc->m_expected_failures); + xml.endElement(); + + xml.endElement(); + } + + void test_case_exception(const TestCaseException& e) override { + DOCTEST_LOCK_MUTEX(mutex) + + xml.scopedElement("Exception") + .writeAttribute("crash", e.is_crash) + .writeText(e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature& in) override { + xml.startElement("SubCase") + .writeAttribute("name", in.m_name) + .writeAttribute("filename", skipPathFromFilename(in.m_file)) + .writeAttribute("line", line(in.m_line)); + xml.ensureTagClosed(); + } + + void subcase_end() override { xml.endElement(); } + + void log_assert(const AssertData& rb) override { + if(!rb.m_failed && !opt.success) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + xml.startElement("Expression") + .writeAttribute("success", !rb.m_failed) + .writeAttribute("type", assertString(rb.m_at)) + .writeAttribute("filename", skipPathFromFilename(rb.m_file)) + .writeAttribute("line", line(rb.m_line)); + + xml.scopedElement("Original").writeText(rb.m_expr); + + if(rb.m_threw) + xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); + + if(rb.m_at & assertType::is_throws_as) + xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); + if(rb.m_at & assertType::is_throws_with) + xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str()); + if((rb.m_at & assertType::is_normal) && !rb.m_threw) + xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); + + log_contexts(); + + xml.endElement(); + } + + void log_message(const MessageData& mb) override { + DOCTEST_LOCK_MUTEX(mutex) + + xml.startElement("Message") + .writeAttribute("type", failureString(mb.m_severity)) + .writeAttribute("filename", skipPathFromFilename(mb.m_file)) + .writeAttribute("line", line(mb.m_line)); + + xml.scopedElement("Text").writeText(mb.m_string.c_str()); + + log_contexts(); + + xml.endElement(); + } + + void test_case_skipped(const TestCaseData& in) override { + if(opt.no_skipped_summary == false) { + test_case_start_impl(in); + xml.writeAttribute("skipped", "true"); + xml.endElement(); + } + } + }; + + DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter); + + void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) { + if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == + 0) //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " + << Color::None; + + if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional + s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; + } else if((rb.m_at & assertType::is_throws_as) && + (rb.m_at & assertType::is_throws_with)) { //!OCLINT + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string.c_str() + << "\", " << rb.m_exception_type << " ) " << Color::None; + if(rb.m_threw) { + if(!rb.m_failed) { + s << "threw as expected!\n"; + } else { + s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; + } + } else { + s << "did NOT throw at all!\n"; + } + } else if(rb.m_at & + assertType::is_throws_as) { //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " + << rb.m_exception_type << " ) " << Color::None + << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" : + "threw a DIFFERENT exception: ") : + "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } else if(rb.m_at & + assertType::is_throws_with) { //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string.c_str() + << "\" ) " << Color::None + << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : + "threw a DIFFERENT exception: ") : + "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional + s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan + << rb.m_exception << "\n"; + } else { + s << (rb.m_threw ? "THREW exception: " : + (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); + if(rb.m_threw) + s << rb.m_exception << "\n"; + else + s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n"; + } + } + + // TODO: + // - log_message() + // - respond to queries + // - honor remaining options + // - more attributes in tags + struct JUnitReporter : public IReporter + { + XmlWriter xml; + DOCTEST_DECLARE_MUTEX(mutex) + Timer timer; + std::vector deepestSubcaseStackNames; + + struct JUnitTestCaseData + { + static std::string getCurrentTimestamp() { + // Beware, this is not reentrant because of backward compatibility issues + // Also, UTC only, again because of backward compatibility (%z is C++11) + time_t rawtime; + std::time(&rawtime); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + + std::tm timeInfo; +#ifdef DOCTEST_PLATFORM_WINDOWS + gmtime_s(&timeInfo, &rawtime); +#else // DOCTEST_PLATFORM_WINDOWS + gmtime_r(&rawtime, &timeInfo); +#endif // DOCTEST_PLATFORM_WINDOWS + + char timeStamp[timeStampSize]; + const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; + + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); + return std::string(timeStamp); + } + + struct JUnitTestMessage + { + JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details) + : message(_message), type(_type), details(_details) {} + + JUnitTestMessage(const std::string& _message, const std::string& _details) + : message(_message), type(), details(_details) {} + + std::string message, type, details; + }; + + struct JUnitTestCase + { + JUnitTestCase(const std::string& _classname, const std::string& _name) + : classname(_classname), name(_name), time(0), failures() {} + + std::string classname, name; + double time; + std::vector failures, errors; + }; + + void add(const std::string& classname, const std::string& name) { + testcases.emplace_back(classname, name); + } + + void appendSubcaseNamesToLastTestcase(std::vector nameStack) { + for(auto& curr: nameStack) + if(curr.size()) + testcases.back().name += std::string("/") + curr.c_str(); + } + + void addTime(double time) { + if(time < 1e-4) + time = 0; + testcases.back().time = time; + totalSeconds += time; + } + + void addFailure(const std::string& message, const std::string& type, const std::string& details) { + testcases.back().failures.emplace_back(message, type, details); + ++totalFailures; + } + + void addError(const std::string& message, const std::string& details) { + testcases.back().errors.emplace_back(message, details); + ++totalErrors; + } + + std::vector testcases; + double totalSeconds = 0; + int totalErrors = 0, totalFailures = 0; + }; + + JUnitTestCaseData testCaseData; + + // caching pointers/references to objects of these types - safe to do + const ContextOptions& opt; + const TestCaseData* tc = nullptr; + + JUnitReporter(const ContextOptions& co) + : xml(*co.cout) + , opt(co) {} + + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData&) override { + xml.writeDeclaration(); + } + + void test_run_start() override { + xml.writeDeclaration(); + } + + void test_run_end(const TestRunStats& p) override { + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); +#ifdef DOCTEST_PLATFORM_WINDOWS + if(binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); +#endif // DOCTEST_PLATFORM_WINDOWS + xml.startElement("testsuites"); + xml.startElement("testsuite").writeAttribute("name", binary_name) + .writeAttribute("errors", testCaseData.totalErrors) + .writeAttribute("failures", testCaseData.totalFailures) + .writeAttribute("tests", p.numAsserts); + if(opt.no_time_in_output == false) { + xml.writeAttribute("time", testCaseData.totalSeconds); + xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp()); + } + if(opt.no_version == false) + xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR); + + for(const auto& testCase : testCaseData.testcases) { + xml.startElement("testcase") + .writeAttribute("classname", testCase.classname) + .writeAttribute("name", testCase.name); + if(opt.no_time_in_output == false) + xml.writeAttribute("time", testCase.time); + // This is not ideal, but it should be enough to mimic gtest's junit output. + xml.writeAttribute("status", "run"); + + for(const auto& failure : testCase.failures) { + xml.scopedElement("failure") + .writeAttribute("message", failure.message) + .writeAttribute("type", failure.type) + .writeText(failure.details, false); + } + + for(const auto& error : testCase.errors) { + xml.scopedElement("error") + .writeAttribute("message", error.message) + .writeText(error.details); + } + + xml.endElement(); + } + xml.endElement(); + xml.endElement(); + } + + void test_case_start(const TestCaseData& in) override { + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + timer.start(); + } + + void test_case_reenter(const TestCaseData& in) override { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + + timer.start(); + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + } + + void test_case_end(const CurrentTestCaseStats&) override { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + } + + void test_case_exception(const TestCaseException& e) override { + DOCTEST_LOCK_MUTEX(mutex) + testCaseData.addError("exception", e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature& in) override { + deepestSubcaseStackNames.push_back(in.m_name); + } + + void subcase_end() override {} + + void log_assert(const AssertData& rb) override { + if(!rb.m_failed) // report only failures & ignore the `success` option + return; + + DOCTEST_LOCK_MUTEX(mutex) + + std::ostringstream os; + os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(") + << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; + + fulltext_log_assert_to_stream(os, rb); + log_contexts(os); + testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); + } + + void log_message(const MessageData& mb) override { + if(mb.m_severity & assertType::is_warn) // report only failures + return; + + DOCTEST_LOCK_MUTEX(mutex) + + std::ostringstream os; + os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(") + << line(mb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; + + os << mb.m_string.c_str() << "\n"; + log_contexts(os); + + testCaseData.addFailure(mb.m_string.c_str(), + mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", os.str()); + } + + void test_case_skipped(const TestCaseData&) override {} + + void log_contexts(std::ostringstream& s) { + int num_contexts = get_num_active_contexts(); + if(num_contexts) { + auto contexts = get_active_contexts(); + + s << " logged: "; + for(int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); + s << std::endl; + } + } + } + }; + + DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter); + + struct Whitespace + { + int nrSpaces; + explicit Whitespace(int nr) + : nrSpaces(nr) {} + }; + + std::ostream& operator<<(std::ostream& out, const Whitespace& ws) { + if(ws.nrSpaces != 0) + out << std::setw(ws.nrSpaces) << ' '; + return out; + } + + struct ConsoleReporter : public IReporter + { + std::ostream& s; + bool hasLoggedCurrentTestStart; + std::vector subcasesStack; + size_t currentSubcaseLevel; + DOCTEST_DECLARE_MUTEX(mutex) + + // caching pointers/references to objects of these types - safe to do + const ContextOptions& opt; + const TestCaseData* tc; + + ConsoleReporter(const ContextOptions& co) + : s(*co.cout) + , opt(co) {} + + ConsoleReporter(const ContextOptions& co, std::ostream& ostr) + : s(ostr) + , opt(co) {} + + // ========================================================================================= + // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE + // ========================================================================================= + + void separator_to_stream() { + s << Color::Yellow + << "===============================================================================" + "\n"; + } + + const char* getSuccessOrFailString(bool success, assertType::Enum at, + const char* success_str) { + if(success) + return success_str; + return failureString(at); + } + + Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) { + return success ? Color::BrightGreen : + (at & assertType::is_warn) ? Color::Yellow : Color::Red; + } + + void successOrFailColoredStringToStream(bool success, assertType::Enum at, + const char* success_str = "SUCCESS") { + s << getSuccessOrFailColor(success, at) + << getSuccessOrFailString(success, at, success_str) << ": "; + } + + void log_contexts() { + int num_contexts = get_num_active_contexts(); + if(num_contexts) { + auto contexts = get_active_contexts(); + + s << Color::None << " logged: "; + for(int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); + s << "\n"; + } + } + + s << "\n"; + } + + // this was requested to be made virtual so users could override it + virtual void file_line_to_stream(const char* file, int line, + const char* tail = "") { + s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(") + << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option + << (opt.gnu_file_line ? ":" : "):") << tail; + } + + void logTestStart() { + if(hasLoggedCurrentTestStart) + return; + + separator_to_stream(); + file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n"); + if(tc->m_description) + s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n"; + if(tc->m_test_suite && tc->m_test_suite[0] != '\0') + s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n"; + if(strncmp(tc->m_name, " Scenario:", 11) != 0) + s << Color::Yellow << "TEST CASE: "; + s << Color::None << tc->m_name << "\n"; + + for(size_t i = 0; i < currentSubcaseLevel; ++i) { + if(subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + + if(currentSubcaseLevel != subcasesStack.size()) { + s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None; + for(size_t i = 0; i < subcasesStack.size(); ++i) { + if(subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + } + + s << "\n"; + + hasLoggedCurrentTestStart = true; + } + + void printVersion() { + if(opt.no_version == false) + s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \"" + << DOCTEST_VERSION_STR << "\"\n"; + } + + void printIntro() { + if(opt.no_intro == false) { + printVersion(); + s << Color::Cyan << "[doctest] " << Color::None + << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n"; + } + } + + void printHelp() { + int sizePrefixDisplay = static_cast(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY)); + printVersion(); + // clang-format off + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n"; + s << Color::Cyan << "[doctest] " << Color::None; + s << "filter values: \"str1,str2,str3\" (comma separated strings)\n"; + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "filters use wildcards for matching strings\n"; + s << Color::Cyan << "[doctest] " << Color::None; + s << "something passes a filter if any of the strings in a filter matches\n"; +#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"" DOCTEST_CONFIG_OPTIONS_PREFIX "\" PREFIX!!!\n"; +#endif + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "Query flags - the program quits after them. Available:\n\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "?, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "help, -" DOCTEST_OPTIONS_PREFIX_DISPLAY "h " + << Whitespace(sizePrefixDisplay*0) << "prints this message\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "v, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "version " + << Whitespace(sizePrefixDisplay*1) << "prints the version\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "c, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "count " + << Whitespace(sizePrefixDisplay*1) << "prints the number of matching tests\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ltc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-cases " + << Whitespace(sizePrefixDisplay*1) << "lists all matching tests by name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-suites " + << Whitespace(sizePrefixDisplay*1) << "lists all matching test suites\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-reporters " + << Whitespace(sizePrefixDisplay*1) << "lists all registered reporters\n\n"; + // ================================================================================== << 79 + s << Color::Cyan << "[doctest] " << Color::None; + s << "The available / options/filters are:\n\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case= " + << Whitespace(sizePrefixDisplay*1) << "filters tests by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case-exclude= " + << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file= " + << Whitespace(sizePrefixDisplay*1) << "filters tests by their file\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sfe, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file-exclude= " + << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their file\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite= " + << Whitespace(sizePrefixDisplay*1) << "filters tests by their test suite\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tse, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite-exclude= " + << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their test suite\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase= " + << Whitespace(sizePrefixDisplay*1) << "filters subcases by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-exclude= " + << Whitespace(sizePrefixDisplay*1) << "filters OUT subcases by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "r, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "reporters= " + << Whitespace(sizePrefixDisplay*1) << "reporters to use (console is default)\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "o, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "out= " + << Whitespace(sizePrefixDisplay*1) << "output filename\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by= " + << Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n"; + s << Whitespace(sizePrefixDisplay*3) << " - [file/suite/name/rand/none]\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed= " + << Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first= " + << Whitespace(sizePrefixDisplay*1) << "the first test passing the filters to\n"; + s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "l, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "last= " + << Whitespace(sizePrefixDisplay*1) << "the last test passing the filters to\n"; + s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "aa, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "abort-after= " + << Whitespace(sizePrefixDisplay*1) << "stop after failed assertions\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "scfl,--" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-filter-levels= " + << Whitespace(sizePrefixDisplay*1) << "apply filters for the first levels\n"; + s << Color::Cyan << "\n[doctest] " << Color::None; + s << "Bool options - can be used like flags and true is assumed. Available:\n\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "s, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "success= " + << Whitespace(sizePrefixDisplay*1) << "include successful assertions in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "cs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "case-sensitive= " + << Whitespace(sizePrefixDisplay*1) << "filters being treated as case sensitive\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "e, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "exit= " + << Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration= " + << Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal= " + << Whitespace(sizePrefixDisplay*1) << "minimal console output (only failures)\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet= " + << Whitespace(sizePrefixDisplay*1) << "no console output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw= " + << Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode= " + << Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run= " + << Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro= " + << Whitespace(sizePrefixDisplay*1) << "omit the framework intro in the output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version= " + << Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors= " + << Whitespace(sizePrefixDisplay*1) << "disables colors in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "fc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "force-colors= " + << Whitespace(sizePrefixDisplay*1) << "use colors even when not in a tty\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nb, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-breaks= " + << Whitespace(sizePrefixDisplay*1) << "disables breakpoints in debuggers\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ns, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-skip= " + << Whitespace(sizePrefixDisplay*1) << "don't skip test cases marked as skip\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "gfl, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "gnu-file-line= " + << Whitespace(sizePrefixDisplay*1) << ":n: vs (n): for line numbers in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "npf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-path-filenames= " + << Whitespace(sizePrefixDisplay*1) << "only filenames and no paths in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers= " + << Whitespace(sizePrefixDisplay*1) << "0 instead of real line numbers in output\n"; + // ================================================================================== << 79 + // clang-format on + + s << Color::Cyan << "\n[doctest] " << Color::None; + s << "for more information visit the project documentation\n\n"; + } + + void printRegisteredReporters() { + printVersion(); + auto printReporters = [this] (const reporterMap& reporters, const char* type) { + if(reporters.size()) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n"; + for(auto& curr : reporters) + s << "priority: " << std::setw(5) << curr.first.first + << " name: " << curr.first.second << "\n"; + } + }; + printReporters(getListeners(), "listeners"); + printReporters(getReporters(), "reporters"); + } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData& in) override { + if(opt.version) { + printVersion(); + } else if(opt.help) { + printHelp(); + } else if(opt.list_reporters) { + printRegisteredReporters(); + } else if(opt.count || opt.list_test_cases) { + if(opt.list_test_cases) { + s << Color::Cyan << "[doctest] " << Color::None + << "listing all test case names\n"; + separator_to_stream(); + } + + for(unsigned i = 0; i < in.num_data; ++i) + s << Color::None << in.data[i]->m_name << "\n"; + + separator_to_stream(); + + s << Color::Cyan << "[doctest] " << Color::None + << "unskipped test cases passing the current filters: " + << g_cs->numTestCasesPassingFilters << "\n"; + + } else if(opt.list_test_suites) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n"; + separator_to_stream(); + + for(unsigned i = 0; i < in.num_data; ++i) + s << Color::None << in.data[i]->m_test_suite << "\n"; + + separator_to_stream(); + + s << Color::Cyan << "[doctest] " << Color::None + << "unskipped test cases passing the current filters: " + << g_cs->numTestCasesPassingFilters << "\n"; + s << Color::Cyan << "[doctest] " << Color::None + << "test suites with unskipped test cases passing the current filters: " + << g_cs->numTestSuitesPassingFilters << "\n"; + } + } + + void test_run_start() override { + if(!opt.minimal) + printIntro(); + } + + void test_run_end(const TestRunStats& p) override { + if(opt.minimal && p.numTestCasesFailed == 0) + return; + + separator_to_stream(); + s << std::dec; + + auto totwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters, static_cast(p.numAsserts))) + 1))); + auto passwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast(p.numAsserts - p.numAssertsFailed))) + 1))); + auto failwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesFailed, static_cast(p.numAssertsFailed))) + 1))); + const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; + s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth) + << p.numTestCasesPassingFilters << " | " + << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : + Color::Green) + << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" + << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) + << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |"; + if(opt.no_skipped_summary == false) { + const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; + s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped + << " skipped" << Color::None; + } + s << "\n"; + s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth) + << p.numAsserts << " | " + << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) + << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None + << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) + << p.numAssertsFailed << " failed" << Color::None << " |\n"; + s << Color::Cyan << "[doctest] " << Color::None + << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) + << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl; + } + + void test_case_start(const TestCaseData& in) override { + hasLoggedCurrentTestStart = false; + tc = ∈ + subcasesStack.clear(); + currentSubcaseLevel = 0; + } + + void test_case_reenter(const TestCaseData&) override { + subcasesStack.clear(); + } + + void test_case_end(const CurrentTestCaseStats& st) override { + if(tc->m_no_output) + return; + + // log the preamble of the test case only if there is something + // else to print - something other than that an assert has failed + if(opt.duration || + (st.failure_flags && st.failure_flags != static_cast(TestCaseFailureReason::AssertFailure))) + logTestStart(); + + if(opt.duration) + s << Color::None << std::setprecision(6) << std::fixed << st.seconds + << " s: " << tc->m_name << "\n"; + + if(st.failure_flags & TestCaseFailureReason::Timeout) + s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6) + << std::fixed << tc->m_timeout << "!\n"; + + if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) { + s << Color::Red << "Should have failed but didn't! Marking it as failed!\n"; + } else if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) { + s << Color::Yellow << "Failed as expected so marking it as not failed\n"; + } else if(st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) { + s << Color::Yellow << "Allowed to fail so marking it as not failed\n"; + } else if(st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) { + s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures + << " times so marking it as failed!\n"; + } else if(st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) { + s << Color::Yellow << "Failed exactly " << tc->m_expected_failures + << " times as expected so marking it as not failed!\n"; + } + if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { + s << Color::Red << "Aborting - too many failed asserts!\n"; + } + s << Color::None; // lgtm [cpp/useless-expression] + } + + void test_case_exception(const TestCaseException& e) override { + DOCTEST_LOCK_MUTEX(mutex) + if(tc->m_no_output) + return; + + logTestStart(); + + file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); + successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require : + assertType::is_check); + s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ") + << Color::Cyan << e.error_string << "\n"; + + int num_stringified_contexts = get_num_stringified_contexts(); + if(num_stringified_contexts) { + auto stringified_contexts = get_stringified_contexts(); + s << Color::None << " logged: "; + for(int i = num_stringified_contexts; i > 0; --i) { + s << (i == num_stringified_contexts ? "" : " ") + << stringified_contexts[i - 1] << "\n"; + } + } + s << "\n" << Color::None; + } + + void subcase_start(const SubcaseSignature& subc) override { + subcasesStack.push_back(subc); + ++currentSubcaseLevel; + hasLoggedCurrentTestStart = false; + } + + void subcase_end() override { + --currentSubcaseLevel; + hasLoggedCurrentTestStart = false; + } + + void log_assert(const AssertData& rb) override { + if((!rb.m_failed && !opt.success) || tc->m_no_output) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + logTestStart(); + + file_line_to_stream(rb.m_file, rb.m_line, " "); + successOrFailColoredStringToStream(!rb.m_failed, rb.m_at); + + fulltext_log_assert_to_stream(s, rb); + + log_contexts(); + } + + void log_message(const MessageData& mb) override { + if(tc->m_no_output) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + logTestStart(); + + file_line_to_stream(mb.m_file, mb.m_line, " "); + s << getSuccessOrFailColor(false, mb.m_severity) + << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity, + "MESSAGE") << ": "; + s << Color::None << mb.m_string << "\n"; + log_contexts(); + } + + void test_case_skipped(const TestCaseData&) override {} + }; + + DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter); + +#ifdef DOCTEST_PLATFORM_WINDOWS + struct DebugOutputWindowReporter : public ConsoleReporter + { + DOCTEST_THREAD_LOCAL static std::ostringstream oss; + + DebugOutputWindowReporter(const ContextOptions& co) + : ConsoleReporter(co, oss) {} + +#define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \ + void func(type arg) override { \ + bool with_col = g_no_colors; \ + g_no_colors = false; \ + ConsoleReporter::func(arg); \ + if(oss.tellp() != std::streampos{}) { \ + DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ + oss.str(""); \ + } \ + g_no_colors = with_col; \ + } + + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in) + }; + + DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss; +#endif // DOCTEST_PLATFORM_WINDOWS + + // the implementation of parseOption() + bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) { + // going from the end to the beginning and stopping on the first occurrence from the end + for(int i = argc; i > 0; --i) { + auto index = i - 1; + auto temp = std::strstr(argv[index], pattern); + if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue + // eliminate matches in which the chars before the option are not '-' + bool noBadCharsFound = true; + auto curr = argv[index]; + while(curr != temp) { + if(*curr++ != '-') { + noBadCharsFound = false; + break; + } + } + if(noBadCharsFound && argv[index][0] == '-') { + if(value) { + // parsing the value of an option + temp += strlen(pattern); + const unsigned len = strlen(temp); + if(len) { + *value = temp; + return true; + } + } else { + // just a flag - no value + return true; + } + } + } + } + return false; + } + + // parses an option and returns the string after the '=' character + bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr, + const String& defaultVal = String()) { + if(value) + *value = defaultVal; +#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + // offset (normally 3 for "dt-") to skip prefix + if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value)) + return true; +#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + return parseOptionImpl(argc, argv, pattern, value); + } + + // locates a flag on the command line + bool parseFlag(int argc, const char* const* argv, const char* pattern) { + return parseOption(argc, argv, pattern); + } + + // parses a comma separated list of words after a pattern in one of the arguments in argv + bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern, + std::vector& res) { + String filtersString; + if(parseOption(argc, argv, pattern, &filtersString)) { + // tokenize with "," as a separator, unless escaped with backslash + std::ostringstream s; + auto flush = [&s, &res]() { + auto string = s.str(); + if(string.size() > 0) { + res.push_back(string.c_str()); + } + s.str(""); + }; + + bool seenBackslash = false; + const char* current = filtersString.c_str(); + const char* end = current + strlen(current); + while(current != end) { + char character = *current++; + if(seenBackslash) { + seenBackslash = false; + if(character == ',' || character == '\\') { + s.put(character); + continue; + } + s.put('\\'); + } + if(character == '\\') { + seenBackslash = true; + } else if(character == ',') { + flush(); + } else { + s.put(character); + } + } + + if(seenBackslash) { + s.put('\\'); + } + flush(); + return true; + } + return false; + } + + enum optionType + { + option_bool, + option_int + }; + + // parses an int/bool option from the command line + bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type, + int& res) { + String parsedValue; + if(!parseOption(argc, argv, pattern, &parsedValue)) + return false; + + if(type) { + // integer + // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse... + int theInt = std::atoi(parsedValue.c_str()); + if (theInt != 0) { + res = theInt; //!OCLINT parameter reassignment + return true; + } + } else { + // boolean + const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1 + const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1 + + // if the value matches any of the positive/negative possibilities + for (unsigned i = 0; i < 4; i++) { + if (parsedValue.compare(positive[i], true) == 0) { + res = 1; //!OCLINT parameter reassignment + return true; + } + if (parsedValue.compare(negative[i], true) == 0) { + res = 0; //!OCLINT parameter reassignment + return true; + } + } + } + return false; + } +} // namespace + +Context::Context(int argc, const char* const* argv) + : p(new detail::ContextState) { + parseArgs(argc, argv, true); + if(argc) + p->binary_name = argv[0]; +} + +Context::~Context() { + if(g_cs == p) + g_cs = nullptr; + delete p; +} + +void Context::applyCommandLine(int argc, const char* const* argv) { + parseArgs(argc, argv); + if(argc) + p->binary_name = argv[0]; +} + +// parses args +void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { + using namespace detail; + + // clang-format off + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file=", p->filters[0]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sf=", p->filters[0]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file-exclude=",p->filters[1]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sfe=", p->filters[1]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite=", p->filters[2]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ts=", p->filters[2]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite-exclude=", p->filters[3]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tse=", p->filters[3]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case=", p->filters[4]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tc=", p->filters[4]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case-exclude=", p->filters[5]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tce=", p->filters[5]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase=", p->filters[6]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sc=", p->filters[6]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase-exclude=", p->filters[7]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sce=", p->filters[7]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "reporters=", p->filters[8]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "r=", p->filters[8]); + // clang-format on + + int intRes = 0; + String strRes; + +#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ + if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ + parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ + p->var = static_cast(intRes); \ + else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ + p->var = true; \ + else if(withDefaults) \ + p->var = default + +#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \ + if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \ + parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \ + p->var = intRes; \ + else if(withDefaults) \ + p->var = default + +#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \ + if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \ + parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \ + withDefaults) \ + p->var = strRes + + // clang-format off + DOCTEST_PARSE_STR_OPTION("out", "o", out, ""); + DOCTEST_PARSE_STR_OPTION("order-by", "ob", order_by, "file"); + DOCTEST_PARSE_INT_OPTION("rand-seed", "rs", rand_seed, 0); + + DOCTEST_PARSE_INT_OPTION("first", "f", first, 0); + DOCTEST_PARSE_INT_OPTION("last", "l", last, UINT_MAX); + + DOCTEST_PARSE_INT_OPTION("abort-after", "aa", abort_after, 0); + DOCTEST_PARSE_INT_OPTION("subcase-filter-levels", "scfl", subcase_filter_levels, INT_MAX); + + DOCTEST_PARSE_AS_BOOL_OR_FLAG("success", "s", success, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-breaks", "nb", no_breaks, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skip", "ns", no_skip, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC)); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false); + // clang-format on + + if(withDefaults) { + p->help = false; + p->version = false; + p->count = false; + p->list_test_cases = false; + p->list_test_suites = false; + p->list_reporters = false; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) { + p->help = true; + p->exit = true; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) { + p->version = true; + p->exit = true; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) { + p->count = true; + p->exit = true; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) { + p->list_test_cases = true; + p->exit = true; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) { + p->list_test_suites = true; + p->exit = true; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) { + p->list_reporters = true; + p->exit = true; + } +} + +// allows the user to add procedurally to the filters from the command line +void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); } + +// allows the user to clear all filters from the command line +void Context::clearFilters() { + for(auto& curr : p->filters) + curr.clear(); +} + +// allows the user to override procedurally the bool options from the command line +void Context::setOption(const char* option, bool value) { + setOption(option, value ? "true" : "false"); +} + +// allows the user to override procedurally the int options from the command line +void Context::setOption(const char* option, int value) { + setOption(option, toString(value).c_str()); +} + +// allows the user to override procedurally the string options from the command line +void Context::setOption(const char* option, const char* value) { + auto argv = String("-") + option + "=" + value; + auto lvalue = argv.c_str(); + parseArgs(1, &lvalue); +} + +// users should query this in their main() and exit the program if true +bool Context::shouldExit() { return p->exit; } + +void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; } + +void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; } + +void Context::setCout(std::ostream* out) { p->cout = out; } + +static class DiscardOStream : public std::ostream +{ +private: + class : public std::streambuf + { + private: + // allowing some buffering decreases the amount of calls to overflow + char buf[1024]; + + protected: + std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; } + + int_type overflow(int_type ch) override { + setp(std::begin(buf), std::end(buf)); + return traits_type::not_eof(ch); + } + } discardBuf; + +public: + DiscardOStream() + : std::ostream(&discardBuf) {} +} discardOut; + +// the main function that does all the filtering and test running +int Context::run() { + using namespace detail; + + // save the old context state in case such was setup - for using asserts out of a testing context + auto old_cs = g_cs; + // this is the current contest + g_cs = p; + is_running_in_test = true; + + g_no_colors = p->no_colors; + p->resetRunData(); + + std::fstream fstr; + if(p->cout == nullptr) { + if(p->quiet) { + p->cout = &discardOut; + } else if(p->out.size()) { + // to a file if specified + fstr.open(p->out.c_str(), std::fstream::out); + p->cout = &fstr; + } else { +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + // stdout by default + p->cout = &std::cout; +#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + return EXIT_FAILURE; +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + } + } + + FatalConditionHandler::allocateAltStackMem(); + + auto cleanup_and_return = [&]() { + FatalConditionHandler::freeAltStackMem(); + + if(fstr.is_open()) + fstr.close(); + + // restore context + g_cs = old_cs; + is_running_in_test = false; + + // we have to free the reporters which were allocated when the run started + for(auto& curr : p->reporters_currently_used) + delete curr; + p->reporters_currently_used.clear(); + + if(p->numTestCasesFailed && !p->no_exitcode) + return EXIT_FAILURE; + return EXIT_SUCCESS; + }; + + // setup default reporter if none is given through the command line + if(p->filters[8].empty()) + p->filters[8].push_back("console"); + + // check to see if any of the registered reporters has been selected + for(auto& curr : getReporters()) { + if(matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive)) + p->reporters_currently_used.push_back(curr.second(*g_cs)); + } + + // TODO: check if there is nothing in reporters_currently_used + + // prepend all listeners + for(auto& curr : getListeners()) + p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); + +#ifdef DOCTEST_PLATFORM_WINDOWS + if(isDebuggerActive() && p->no_debug_output == false) + p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); +#endif // DOCTEST_PLATFORM_WINDOWS + + // handle version, help and no_run + if(p->no_run || p->version || p->help || p->list_reporters) { + DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData()); + + return cleanup_and_return(); + } + + std::vector testArray; + for(auto& curr : getRegisteredTests()) + testArray.push_back(&curr); + p->numTestCases = testArray.size(); + + // sort the collected records + if(!testArray.empty()) { + if(p->order_by.compare("file", true) == 0) { + std::sort(testArray.begin(), testArray.end(), fileOrderComparator); + } else if(p->order_by.compare("suite", true) == 0) { + std::sort(testArray.begin(), testArray.end(), suiteOrderComparator); + } else if(p->order_by.compare("name", true) == 0) { + std::sort(testArray.begin(), testArray.end(), nameOrderComparator); + } else if(p->order_by.compare("rand", true) == 0) { + std::srand(p->rand_seed); + + // random_shuffle implementation + const auto first = &testArray[0]; + for(size_t i = testArray.size() - 1; i > 0; --i) { + int idxToSwap = std::rand() % (i + 1); + + const auto temp = first[i]; + + first[i] = first[idxToSwap]; + first[idxToSwap] = temp; + } + } else if(p->order_by.compare("none", true) == 0) { + // means no sorting - beneficial for death tests which call into the executable + // with a specific test case in mind - we don't want to slow down the startup times + } + } + + std::set testSuitesPassingFilt; + + bool query_mode = p->count || p->list_test_cases || p->list_test_suites; + std::vector queryResults; + + if(!query_mode) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY); + + // invoke the registered functions if they match the filter criteria (or just count them) + for(auto& curr : testArray) { + const auto& tc = *curr; + + bool skip_me = false; + if(tc.m_skip && !p->no_skip) + skip_me = true; + + if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive)) + skip_me = true; + if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive)) + skip_me = true; + if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive)) + skip_me = true; + if(matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive)) + skip_me = true; + if(!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive)) + skip_me = true; + if(matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive)) + skip_me = true; + + if(!skip_me) + p->numTestCasesPassingFilters++; + + // skip the test if it is not in the execution range + if((p->last < p->numTestCasesPassingFilters && p->first <= p->last) || + (p->first > p->numTestCasesPassingFilters)) + skip_me = true; + + if(skip_me) { + if(!query_mode) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc); + continue; + } + + // do not execute the test if we are to only count the number of filter passing tests + if(p->count) + continue; + + // print the name of the test and don't execute it + if(p->list_test_cases) { + queryResults.push_back(&tc); + continue; + } + + // print the name of the test suite if not done already and don't execute it + if(p->list_test_suites) { + if((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') { + queryResults.push_back(&tc); + testSuitesPassingFilt.insert(tc.m_test_suite); + p->numTestSuitesPassingFilters++; + } + continue; + } + + // execute the test if it passes all the filtering + { + p->currentTest = &tc; + + p->failure_flags = TestCaseFailureReason::None; + p->seconds = 0; + + // reset atomic counters + p->numAssertsFailedCurrentTest_atomic = 0; + p->numAssertsCurrentTest_atomic = 0; + + p->fullyTraversedSubcases.clear(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc); + + p->timer.start(); + + bool run_test = true; + + do { + // reset some of the fields for subcases (except for the set of fully passed ones) + p->reachedLeaf = false; + // May not be empty if previous subcase exited via exception. + p->subcaseStack.clear(); + p->currentSubcaseDepth = 0; + + p->shouldLogCurrentException = true; + + // reset stuff for logging with INFO() + p->stringifiedContexts.clear(); + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + try { +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS +// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method) +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable + FatalConditionHandler fatalConditionHandler; // Handle signals + // execute the test + tc.m_test(); + fatalConditionHandler.reset(); +DOCTEST_MSVC_SUPPRESS_WARNING_POP +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + } catch(const TestFailureException&) { + p->failure_flags |= TestCaseFailureReason::AssertFailure; + } catch(...) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, + {translateActiveException(), false}); + p->failure_flags |= TestCaseFailureReason::Exception; + } +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + + // exit this loop if enough assertions have failed - even if there are more subcases + if(p->abort_after > 0 && + p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) { + run_test = false; + p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; + } + + if(!p->nextSubcaseStack.empty() && run_test) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc); + if(p->nextSubcaseStack.empty()) + run_test = false; + } while(run_test); + + p->finalizeTestCaseData(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); + + p->currentTest = nullptr; + + // stop executing tests if enough assertions have failed + if(p->abort_after > 0 && p->numAssertsFailed >= p->abort_after) + break; + } + } + + if(!query_mode) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); + } else { + QueryData qdata; + qdata.run_stats = g_cs; + qdata.data = queryResults.data(); + qdata.num_data = unsigned(queryResults.size()); + DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); + } + + return cleanup_and_return(); +} + +DOCTEST_DEFINE_INTERFACE(IReporter) + +int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); } +const IContextScope* const* IReporter::get_active_contexts() { + return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr; +} + +int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); } +const String* IReporter::get_stringified_contexts() { + return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] : nullptr; +} + +namespace detail { + void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) { + if(isReporter) + getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + else + getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + } +} // namespace detail + +} // namespace doctest + +#endif // DOCTEST_CONFIG_DISABLE + +#ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) // 'function' : must be 'attribute' - see issue #182 +int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); } +DOCTEST_MSVC_SUPPRESS_WARNING_POP +#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN + +DOCTEST_CLANG_SUPPRESS_WARNING_POP +DOCTEST_MSVC_SUPPRESS_WARNING_POP +DOCTEST_GCC_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_POP + +#endif // DOCTEST_LIBRARY_IMPLEMENTATION +#endif // DOCTEST_CONFIG_IMPLEMENT + +#ifdef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN +#undef WIN32_LEAN_AND_MEAN +#undef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN +#endif // DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN + +#ifdef DOCTEST_UNDEF_NOMINMAX +#undef NOMINMAX +#undef DOCTEST_UNDEF_NOMINMAX +#endif // DOCTEST_UNDEF_NOMINMAX diff --git a/util/generate_test_case.py b/util/generate_test_case.py index a2a95163..b59527e9 100755 --- a/util/generate_test_case.py +++ b/util/generate_test_case.py @@ -25,62 +25,66 @@ import jinja2 TEST_CASE_MULTIPLIER = 10000 CLASS_DIAGRAM_TEST_CASE_EXAMPLES = """ - // Check if all classes exist - //REQUIRE_THAT(src, IsClass(_A("A"))); - - // Check if class templates exist - //REQUIRE_THAT(src, IsClassTemplate("A", "T,P,CMP,int N")); - - // Check concepts - //REQUIRE_THAT(src, IsConcept(_A("AConcept"))); - //REQUIRE_THAT(src, - // IsConceptRequirement( - // _A("AConcept"), "sizeof (T) > sizeof (P)")); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + // REQUIRE(HasTitle(src, "Basic class diagram example")); - // Check if all enums exist - //REQUIRE_THAT(src, IsEnum(_A("Lights"))); - - // Check if all inner classes exist - //REQUIRE_THAT(src, IsInnerClass(_A("A"), _A("AA"))); + // REQUIRE(!IsClass(src, "NOSUCHCLASS")); + // REQUIRE(IsAbstractClass(src, "A")); + // REQUIRE(IsClass(src, "B")); + // REQUIRE(IsBaseClass(src, "A", "B")); - // Check if all inheritance relationships exist - //REQUIRE_THAT(src, IsBaseClass(_A("Base"), _A("Child"))); - - // Check if all methods exist - //REQUIRE_THAT(src, (IsMethod("foo"))); - - // Check if all fields exist - //REQUIRE_THAT(src, (IsField("private_member", "int"))); - - // Check if all relationships exist - //REQUIRE_THAT(src, IsAssociation(_A("D"), _A("A"), "-as")); - //REQUIRE_THAT(src, IsDependency(_A("R"), _A("B"))); - //REQUIRE_THAT(src, IsAggregation(_A("R"), _A("D"), "-ag")); - //REQUIRE_THAT(src, IsComposition(_A("R"), _A("D"), "-ac")); - //REQUIRE_THAT(src, IsInstantiation(_A("ABCD::F"), _A("F"))); + // REQUIRE(IsMethod(src, "A", "foo_a")); + + // REQUIRE(IsAssociation(src, "D", "A", "as")); + + // REQUIRE(HasNote(src, "A", "left", "This is class A")); + }); """ SEQUENCE_DIAGRAM_TEST_CASE_EXAMPLES = """ - // Check if all calls exist - //REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("A"), "a()")); - //REQUIRE_THAT(src, HasCall(_A("A"), "a()")); + CHECK_SEQUENCE_DIAGRAM( + config, diagram, *model, + [](const auto &src) { + // REQUIRE(HasTitle(src, "Basic sequence diagram example")); + + REQUIRE(MessageOrder(src, + { + // + // {"tmain()", "A", "A()"}, // + // {"B", "A", "log_result(int)", Static{}} // + })); + + // REQUIRE(!HasMessage(src, {"A", {"detail", "C"}, "add(int,int)"})); + + // REQUIRE(HasComment(src, "t20001 test diagram of type sequence")); + + // REQUIRE(HasMessageComment(src, "tmain()", "Just add 2 numbers")); + }); """ PACKAGE_DIAGRAM_TEST_CASE_EXAMPLES = """ - // Check if all packages exist - //REQUIRE_THAT(src, IsPackage("ns1")); + CHECK_PACKAGE_DIAGRAM(config, diagram, *model, [](const auto &src) { + // REQUIRE(IsNamespacePackage(src, "A"s, "AA"s)); + + // REQUIRE(IsNamespacePackage(src, "B"s, "BB"s, "BBB"s)); + + // REQUIRE(IsDependency(src, "BBB", "A1")); + }); """ INCLUDE_DIAGRAM_TEST_CASE_EXAMPLES = """ - // Check all folders exist - //REQUIRE_THAT(src, IsFolder("lib1")); - - // Check if all files exist - //REQUIRE_THAT(src, IsFile("lib1.h")); - - // Check if all includes exists - //REQUIRE_THAT(src, IsAssociation(_A("t40002.cc"), _A("lib1.h"))); - //REQUIRE_THAT(src, IsDependency(_A("t40001_include1.h"), _A("string"))); + CHECK_INCLUDE_DIAGRAM(config, diagram, *model, [](const auto &src) { + // REQUIRE(IsFolder(src, "include/lib1")); + // REQUIRE(IsFile(src, "include/lib1/lib1.h")); + + // REQUIRE(IsSystemHeader(src, "string")); + + // REQUIRE(IsHeaderDependency( + // src, "src/t40001.cc", "include/t40001_include1.h")); + + // REQUIRE(IsSystemHeaderDependency( + // src, "include/t40001_include1.h", "string")); + }); """ @@ -153,7 +157,10 @@ def main(args): examples = examples_for_type(test_case_type) - variables = dict(type = test_case_type, name = test_case_name, examples = examples) + variables = dict(type = test_case_type, + TYPE = test_case_type.upper(), + name = test_case_name, + examples = examples) generate(environment, variables, '.clang-uml', '.clang-uml', test_case_directory) generate(environment, variables, 't00000.cc', f'{test_case_name}.cc', test_case_directory) diff --git a/util/templates/test_cases/test_case.h b/util/templates/test_cases/test_case.h index 13a7c6c9..8fefc60f 100644 --- a/util/templates/test_cases/test_case.h +++ b/util/templates/test_cases/test_case.h @@ -16,45 +16,13 @@ * limitations under the License. */ -TEST_CASE("{{ name }}", "[test-case][{{ type }}]") +TEST_CASE("{{ name }}") { - auto [config, db] = load_config("{{ name }}"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["{{ name }}_{{ type }}"]; + auto [config, db, diagram, model] = + CHECK_{{ TYPE }}_MODEL("{{ name }}", "{{ name }}_class"); - REQUIRE(diagram->name == "{{ name }}_{{ type }}"); - - auto model = generate_{{ type }}_diagram(*db, diagram); - - REQUIRE(model->name() == "{{ name }}_{{ type }}"); - - { - auto src = generate_{{ type }}_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - - {{ examples }} - - save_puml( - config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_{{ type }}_json(diagram, *model); - - using namespace json; - - save_json(config.output_directory(), diagram->name + ".json", j); - } - - { - auto src = generate_{{ type }}_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + {{ examples }} }

(pred)) - { - if (!m_predicate(m_generator.get())) { - // It might happen that there are no values that pass the - // filter. In that case we throw an exception. - auto has_initial_value = nextImpl(); - if (!has_initial_value) { - Catch::throw_exception(GeneratorException( - "No valid value found in filtered generator")); - } - } - } - - T const &get() const override { return m_generator.get(); } - - bool next() override { return nextImpl(); } - -private: - bool nextImpl() - { - bool success = m_generator.next(); - if (!success) { - return false; - } - while (!m_predicate(m_generator.get()) && - (success = m_generator.next()) == true) - ; - return success; - } -}; - -template -GeneratorWrapper filter(Predicate &&pred, GeneratorWrapper &&generator) -{ - return GeneratorWrapper(std::unique_ptr>( - pf::make_unique>( - std::forward(pred), std::move(generator)))); -} - -template class RepeatGenerator : public IGenerator { - static_assert(!std::is_same::value, - "RepeatGenerator currently does not support bools" - "because of std::vector specialization"); - GeneratorWrapper m_generator; - mutable std::vector m_returned; - size_t m_target_repeats; - size_t m_current_repeat = 0; - size_t m_repeat_index = 0; - -public: - RepeatGenerator(size_t repeats, GeneratorWrapper &&generator) - : m_generator(std::move(generator)) - , m_target_repeats(repeats) - { - assert(m_target_repeats > 0 && - "Repeat generator must repeat at least once"); - } - - T const &get() const override - { - if (m_current_repeat == 0) { - m_returned.push_back(m_generator.get()); - return m_returned.back(); - } - return m_returned[m_repeat_index]; - } - - bool next() override - { - // There are 2 basic cases: - // 1) We are still reading the generator - // 2) We are reading our own cache - - // In the first case, we need to poke the underlying generator. - // If it happily moves, we are left in that state, otherwise it is time - // to start reading from our cache - if (m_current_repeat == 0) { - const auto success = m_generator.next(); - if (!success) { - ++m_current_repeat; - } - return m_current_repeat < m_target_repeats; - } - - // In the second case, we need to move indices forward and check that we - // haven't run up against the end - ++m_repeat_index; - if (m_repeat_index == m_returned.size()) { - m_repeat_index = 0; - ++m_current_repeat; - } - return m_current_repeat < m_target_repeats; - } -}; - -template -GeneratorWrapper repeat(size_t repeats, GeneratorWrapper &&generator) -{ - return GeneratorWrapper( - pf::make_unique>(repeats, std::move(generator))); -} - -template -class MapGenerator : public IGenerator { - // TBD: provide static assert for mapping function, for friendly error - // message - GeneratorWrapper m_generator; - Func m_function; - // To avoid returning dangling reference, we have to save the values - T m_cache; - -public: - template - MapGenerator(F2 &&function, GeneratorWrapper &&generator) - : m_generator(std::move(generator)) - , m_function(std::forward(function)) - , m_cache(m_function(m_generator.get())) - { - } - - T const &get() const override { return m_cache; } - bool next() override - { - const auto success = m_generator.next(); - if (success) { - m_cache = m_function(m_generator.get()); - } - return success; - } -}; - -template > -GeneratorWrapper map(Func &&function, GeneratorWrapper &&generator) -{ - return GeneratorWrapper(pf::make_unique>( - std::forward(function), std::move(generator))); -} - -template -GeneratorWrapper map(Func &&function, GeneratorWrapper &&generator) -{ - return GeneratorWrapper(pf::make_unique>( - std::forward(function), std::move(generator))); -} - -template -class ChunkGenerator final : public IGenerator> { - std::vector m_chunk; - size_t m_chunk_size; - GeneratorWrapper m_generator; - bool m_used_up = false; - -public: - ChunkGenerator(size_t size, GeneratorWrapper generator) - : m_chunk_size(size) - , m_generator(std::move(generator)) - { - m_chunk.reserve(m_chunk_size); - if (m_chunk_size != 0) { - m_chunk.push_back(m_generator.get()); - for (size_t i = 1; i < m_chunk_size; ++i) { - if (!m_generator.next()) { - Catch::throw_exception(GeneratorException( - "Not enough values to initialize the first chunk")); - } - m_chunk.push_back(m_generator.get()); - } - } - } - std::vector const &get() const override { return m_chunk; } - bool next() override - { - m_chunk.clear(); - for (size_t idx = 0; idx < m_chunk_size; ++idx) { - if (!m_generator.next()) { - return false; - } - m_chunk.push_back(m_generator.get()); - } - return true; - } -}; - -template -GeneratorWrapper> chunk( - size_t size, GeneratorWrapper &&generator) -{ - return GeneratorWrapper>( - pf::make_unique>(size, std::move(generator))); -} - -} // namespace Generators -} // namespace Catch - -// end catch_generators_generic.hpp -// start catch_generators_specific.hpp - -// start catch_context.h - -#include - -namespace Catch { - -struct IResultCapture; -struct IRunner; -struct IConfig; -struct IMutableContext; - -using IConfigPtr = std::shared_ptr; - -struct IContext { - virtual ~IContext(); - - virtual IResultCapture *getResultCapture() = 0; - virtual IRunner *getRunner() = 0; - virtual IConfigPtr const &getConfig() const = 0; -}; - -struct IMutableContext : IContext { - virtual ~IMutableContext(); - virtual void setResultCapture(IResultCapture *resultCapture) = 0; - virtual void setRunner(IRunner *runner) = 0; - virtual void setConfig(IConfigPtr const &config) = 0; - -private: - static IMutableContext *currentContext; - friend IMutableContext &getCurrentMutableContext(); - friend void cleanUpContext(); - static void createContext(); -}; - -inline IMutableContext &getCurrentMutableContext() -{ - if (!IMutableContext::currentContext) - IMutableContext::createContext(); - // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) - return *IMutableContext::currentContext; -} - -inline IContext &getCurrentContext() { return getCurrentMutableContext(); } - -void cleanUpContext(); - -class SimplePcg32; -SimplePcg32 &rng(); -} - -// end catch_context.h -// start catch_interfaces_config.h - -// start catch_option.hpp - -namespace Catch { - -// An optional type -template class Option { -public: - Option() - : nullableValue(nullptr) - { - } - Option(T const &_value) - : nullableValue(new(storage) T(_value)) - { - } - Option(Option const &_other) - : nullableValue(_other ? new(storage) T(*_other) : nullptr) - { - } - - ~Option() { reset(); } - - Option &operator=(Option const &_other) - { - if (&_other != this) { - reset(); - if (_other) - nullableValue = new (storage) T(*_other); - } - return *this; - } - Option &operator=(T const &_value) - { - reset(); - nullableValue = new (storage) T(_value); - return *this; - } - - void reset() - { - if (nullableValue) - nullableValue->~T(); - nullableValue = nullptr; - } - - T &operator*() { return *nullableValue; } - T const &operator*() const { return *nullableValue; } - T *operator->() { return nullableValue; } - const T *operator->() const { return nullableValue; } - - T valueOr(T const &defaultValue) const - { - return nullableValue ? *nullableValue : defaultValue; - } - - bool some() const { return nullableValue != nullptr; } - bool none() const { return nullableValue == nullptr; } - - bool operator!() const { return nullableValue == nullptr; } - explicit operator bool() const { return some(); } - -private: - T *nullableValue; - alignas(alignof(T)) char storage[sizeof(T)]; -}; - -} // end namespace Catch - -// end catch_option.hpp -#include -#include -#include -#include -#include - -namespace Catch { - -enum class Verbosity { Quiet = 0, Normal, High }; - -struct WarnAbout { - enum What { Nothing = 0x00, NoAssertions = 0x01, NoTests = 0x02 }; -}; - -struct ShowDurations { - enum OrNot { DefaultForReporter, Always, Never }; -}; -struct RunTests { - enum InWhatOrder { - InDeclarationOrder, - InLexicographicalOrder, - InRandomOrder - }; -}; -struct UseColour { - enum YesOrNo { Auto, Yes, No }; -}; -struct WaitForKeypress { - enum When { - Never, - BeforeStart = 1, - BeforeExit = 2, - BeforeStartAndExit = BeforeStart | BeforeExit - }; -}; - -class TestSpec; - -struct IConfig : NonCopyable { - - virtual ~IConfig(); - - virtual bool allowThrows() const = 0; - virtual std::ostream &stream() const = 0; - virtual std::string name() const = 0; - virtual bool includeSuccessfulResults() const = 0; - virtual bool shouldDebugBreak() const = 0; - virtual bool warnAboutMissingAssertions() const = 0; - virtual bool warnAboutNoTests() const = 0; - virtual int abortAfter() const = 0; - virtual bool showInvisibles() const = 0; - virtual ShowDurations::OrNot showDurations() const = 0; - virtual double minDuration() const = 0; - virtual TestSpec const &testSpec() const = 0; - virtual bool hasTestFilters() const = 0; - virtual std::vector const &getTestsOrTags() const = 0; - virtual RunTests::InWhatOrder runOrder() const = 0; - virtual unsigned int rngSeed() const = 0; - virtual UseColour::YesOrNo useColour() const = 0; - virtual std::vector const &getSectionsToRun() const = 0; - virtual Verbosity verbosity() const = 0; - - virtual bool benchmarkNoAnalysis() const = 0; - virtual int benchmarkSamples() const = 0; - virtual double benchmarkConfidenceInterval() const = 0; - virtual unsigned int benchmarkResamples() const = 0; - virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0; -}; - -using IConfigPtr = std::shared_ptr; -} - -// end catch_interfaces_config.h -// start catch_random_number_generator.h - -#include - -namespace Catch { - -// This is a simple implementation of C++11 Uniform Random Number -// Generator. It does not provide all operators, because Catch2 -// does not use it, but it should behave as expected inside stdlib's -// distributions. -// The implementation is based on the PCG family (http://pcg-random.org) -class SimplePcg32 { - using state_type = std::uint64_t; - -public: - using result_type = std::uint32_t; - static constexpr result_type(min)() { return 0; } - static constexpr result_type(max)() { return static_cast(-1); } - - // Provide some default initial state for the default constructor - SimplePcg32() - : SimplePcg32(0xed743cc4U) - { - } - - explicit SimplePcg32(result_type seed_); - - void seed(result_type seed_); - void discard(uint64_t skip); - - result_type operator()(); - -private: - friend bool operator==(SimplePcg32 const &lhs, SimplePcg32 const &rhs); - friend bool operator!=(SimplePcg32 const &lhs, SimplePcg32 const &rhs); - - // In theory we also need operator<< and operator>> - // In practice we do not use them, so we will skip them for now - - std::uint64_t m_state; - // This part of the state determines which "stream" of the numbers - // is chosen -- we take it as a constant for Catch2, so we only - // need to deal with seeding the main state. - // Picked by reading 8 bytes from `/dev/random` :-) - static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL; -}; - -} // end namespace Catch - -// end catch_random_number_generator.h -#include - -namespace Catch { -namespace Generators { - -template -class RandomFloatingGenerator final : public IGenerator { - Catch::SimplePcg32 &m_rng; - std::uniform_real_distribution m_dist; - Float m_current_number; - -public: - RandomFloatingGenerator(Float a, Float b) - : m_rng(rng()) - , m_dist(a, b) - { - static_cast(next()); - } - - Float const &get() const override { return m_current_number; } - bool next() override - { - m_current_number = m_dist(m_rng); - return true; - } -}; - -template -class RandomIntegerGenerator final : public IGenerator { - Catch::SimplePcg32 &m_rng; - std::uniform_int_distribution m_dist; - Integer m_current_number; - -public: - RandomIntegerGenerator(Integer a, Integer b) - : m_rng(rng()) - , m_dist(a, b) - { - static_cast(next()); - } - - Integer const &get() const override { return m_current_number; } - bool next() override - { - m_current_number = m_dist(m_rng); - return true; - } -}; - -// TODO: Ideally this would be also constrained against the various char types, -// but I don't expect users to run into that in practice. -template -typename std::enable_if::value && - !std::is_same::value, - GeneratorWrapper>::type -random(T a, T b) -{ - return GeneratorWrapper( - pf::make_unique>(a, b)); -} - -template -typename std::enable_if::value, - GeneratorWrapper>::type -random(T a, T b) -{ - return GeneratorWrapper( - pf::make_unique>(a, b)); -} - -template class RangeGenerator final : public IGenerator { - T m_current; - T m_end; - T m_step; - bool m_positive; - -public: - RangeGenerator(T const &start, T const &end, T const &step) - : m_current(start) - , m_end(end) - , m_step(step) - , m_positive(m_step > T(0)) - { - assert(m_current != m_end && "Range start and end cannot be equal"); - assert(m_step != T(0) && "Step size cannot be zero"); - assert(((m_positive && m_current <= m_end) || - (!m_positive && m_current >= m_end)) && - "Step moves away from end"); - } - - RangeGenerator(T const &start, T const &end) - : RangeGenerator(start, end, (start < end) ? T(1) : T(-1)) - { - } - - T const &get() const override { return m_current; } - - bool next() override - { - m_current += m_step; - return (m_positive) ? (m_current < m_end) : (m_current > m_end); - } -}; - -template -GeneratorWrapper range(T const &start, T const &end, T const &step) -{ - static_assert(std::is_arithmetic::value && !std::is_same::value, - "Type must be numeric"); - return GeneratorWrapper( - pf::make_unique>(start, end, step)); -} - -template GeneratorWrapper range(T const &start, T const &end) -{ - static_assert(std::is_integral::value && !std::is_same::value, - "Type must be an integer"); - return GeneratorWrapper(pf::make_unique>(start, end)); -} - -template class IteratorGenerator final : public IGenerator { - static_assert(!std::is_same::value, - "IteratorGenerator currently does not support bools" - "because of std::vector specialization"); - - std::vector m_elems; - size_t m_current = 0; - -public: - template - IteratorGenerator(InputIterator first, InputSentinel last) - : m_elems(first, last) - { - if (m_elems.empty()) { - Catch::throw_exception(GeneratorException( - "IteratorGenerator received no valid values")); - } - } - - T const &get() const override { return m_elems[m_current]; } - - bool next() override - { - ++m_current; - return m_current != m_elems.size(); - } -}; - -template ::value_type> -GeneratorWrapper from_range(InputIterator from, InputSentinel to) -{ - return GeneratorWrapper( - pf::make_unique>(from, to)); -} - -template -GeneratorWrapper from_range(Container const &cnt) -{ - return GeneratorWrapper( - pf::make_unique>(cnt.begin(), cnt.end())); -} - -} // namespace Generators -} // namespace Catch - -// end catch_generators_specific.hpp - -// These files are included here so the single_include script doesn't put them -// in the conditionally compiled sections -// start catch_test_case_info.h - -#include -#include -#include - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - -struct ITestInvoker; - -struct TestCaseInfo { - enum SpecialProperties { - None = 0, - IsHidden = 1 << 1, - ShouldFail = 1 << 2, - MayFail = 1 << 3, - Throws = 1 << 4, - NonPortable = 1 << 5, - Benchmark = 1 << 6 - }; - - TestCaseInfo(std::string const &_name, std::string const &_className, - std::string const &_description, std::vector const &_tags, - SourceLineInfo const &_lineInfo); - - friend void setTags( - TestCaseInfo &testCaseInfo, std::vector tags); - - bool isHidden() const; - bool throws() const; - bool okToFail() const; - bool expectedToFail() const; - - std::string tagsAsString() const; - - std::string name; - std::string className; - std::string description; - std::vector tags; - std::vector lcaseTags; - SourceLineInfo lineInfo; - SpecialProperties properties; -}; - -class TestCase : public TestCaseInfo { -public: - TestCase(ITestInvoker *testCase, TestCaseInfo &&info); - - TestCase withName(std::string const &_newName) const; - - void invoke() const; - - TestCaseInfo const &getTestCaseInfo() const; - - bool operator==(TestCase const &other) const; - bool operator<(TestCase const &other) const; - -private: - std::shared_ptr test; -}; - -TestCase makeTestCase(ITestInvoker *testCase, std::string const &className, - NameAndTags const &nameAndTags, SourceLineInfo const &lineInfo); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// end catch_test_case_info.h -// start catch_interfaces_runner.h - -namespace Catch { - -struct IRunner { - virtual ~IRunner(); - virtual bool aborting() const = 0; -}; -} - -// end catch_interfaces_runner.h - -#ifdef __OBJC__ -// start catch_objc.hpp - -#import - -#include - -// NB. Any general catch headers included here must be included -// in catch.hpp first to make sure they are included by the single -// header for non obj-usage - -/////////////////////////////////////////////////////////////////////////////// -// This protocol is really only here for (self) documenting purposes, since -// all its methods are optional. -@protocol OcFixture - -@optional - -- (void)setUp; -- (void)tearDown; - -@end - -namespace Catch { - -class OcMethod : public ITestInvoker { - -public: - OcMethod(Class cls, SEL sel) - : m_cls(cls) - , m_sel(sel) - { - } - - virtual void invoke() const - { - id obj = [[m_cls alloc] init]; - - performOptionalSelector(obj, @selector(setUp)); - performOptionalSelector(obj, m_sel); - performOptionalSelector(obj, @selector(tearDown)); - - arcSafeRelease(obj); - } - -private: - virtual ~OcMethod() { } - - Class m_cls; - SEL m_sel; -}; - -namespace Detail { - -inline std::string getAnnotation(Class cls, std::string const &annotationName, - std::string const &testCaseName) -{ - NSString *selStr = - [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), - testCaseName.c_str()]; - SEL sel = NSSelectorFromString(selStr); - arcSafeRelease(selStr); - id value = performOptionalSelector(cls, sel); - if (value) - return [(NSString *)value UTF8String]; - return ""; -} -} - -inline std::size_t registerTestMethods() -{ - std::size_t noTestMethods = 0; - int noClasses = objc_getClassList(nullptr, 0); - - Class *classes = - (CATCH_UNSAFE_UNRETAINED Class *)malloc(sizeof(Class) * noClasses); - objc_getClassList(classes, noClasses); - - for (int c = 0; c < noClasses; c++) { - Class cls = classes[c]; - { - u_int count; - Method *methods = class_copyMethodList(cls, &count); - for (u_int m = 0; m < count; m++) { - SEL selector = method_getName(methods[m]); - std::string methodName = sel_getName(selector); - if (startsWith(methodName, "Catch_TestCase_")) { - std::string testCaseName = methodName.substr(15); - std::string name = - Detail::getAnnotation(cls, "Name", testCaseName); - std::string desc = - Detail::getAnnotation(cls, "Description", testCaseName); - const char *className = class_getName(cls); - - getMutableRegistryHub().registerTest( - makeTestCase(new OcMethod(cls, selector), className, - NameAndTags(name.c_str(), desc.c_str()), - SourceLineInfo("", 0))); - noTestMethods++; - } - } - free(methods); - } - } - return noTestMethods; -} - -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) - -namespace Matchers { -namespace Impl { -namespace NSStringMatchers { - -struct StringHolder : MatcherBase { - StringHolder(NSString *substr) - : m_substr([substr copy]) - { - } - StringHolder(StringHolder const &other) - : m_substr([other.m_substr copy]) - { - } - StringHolder() { arcSafeRelease(m_substr); } - - bool match(NSString *str) const override { return false; } - - NSString *CATCH_ARC_STRONG m_substr; -}; - -struct Equals : StringHolder { - Equals(NSString *substr) - : StringHolder(substr) - { - } - - bool match(NSString *str) const override - { - return (str != nil || m_substr == nil) && - [str isEqualToString:m_substr]; - } - - std::string describe() const override - { - return "equals string: " + Catch::Detail::stringify(m_substr); - } -}; - -struct Contains : StringHolder { - Contains(NSString *substr) - : StringHolder(substr) - { - } - - bool match(NSString *str) const override - { - return (str != nil || m_substr == nil) && - [str rangeOfString:m_substr].location != NSNotFound; - } - - std::string describe() const override - { - return "contains string: " + Catch::Detail::stringify(m_substr); - } -}; - -struct StartsWith : StringHolder { - StartsWith(NSString *substr) - : StringHolder(substr) - { - } - - bool match(NSString *str) const override - { - return (str != nil || m_substr == nil) && - [str rangeOfString:m_substr].location == 0; - } - - std::string describe() const override - { - return "starts with: " + Catch::Detail::stringify(m_substr); - } -}; -struct EndsWith : StringHolder { - EndsWith(NSString *substr) - : StringHolder(substr) - { - } - - bool match(NSString *str) const override - { - return (str != nil || m_substr == nil) && - [str rangeOfString:m_substr].location == - [str length] - [m_substr length]; - } - - std::string describe() const override - { - return "ends with: " + Catch::Detail::stringify(m_substr); - } -}; - -} // namespace NSStringMatchers -} // namespace Impl - -inline Impl::NSStringMatchers::Equals Equals(NSString *substr) -{ - return Impl::NSStringMatchers::Equals(substr); -} - -inline Impl::NSStringMatchers::Contains Contains(NSString *substr) -{ - return Impl::NSStringMatchers::Contains(substr); -} - -inline Impl::NSStringMatchers::StartsWith StartsWith(NSString *substr) -{ - return Impl::NSStringMatchers::StartsWith(substr); -} - -inline Impl::NSStringMatchers::EndsWith EndsWith(NSString *substr) -{ - return Impl::NSStringMatchers::EndsWith(substr); -} - -} // namespace Matchers - -using namespace Matchers; - -#endif // CATCH_CONFIG_DISABLE_MATCHERS - -} // namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define OC_MAKE_UNIQUE_NAME(root, uniqueSuffix) root##uniqueSuffix -#define OC_TEST_CASE2(name, desc, uniqueSuffix) \ - +(NSString *)OC_MAKE_UNIQUE_NAME(Catch_Name_test_, uniqueSuffix) \ - { \ - return @name; \ - } \ - +(NSString *)OC_MAKE_UNIQUE_NAME(Catch_Description_test_, uniqueSuffix) \ - { \ - return @desc; \ - } \ - -(void)OC_MAKE_UNIQUE_NAME(Catch_TestCase_test_, uniqueSuffix) - -#define OC_TEST_CASE(name, desc) OC_TEST_CASE2(name, desc, __LINE__) - -// end catch_objc.hpp -#endif - -// Benchmarking needs the externally-facing parts of reporters to work -#if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || \ - defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -// start catch_external_interfaces.h - -// start catch_reporter_bases.hpp - -// start catch_interfaces_reporter.h - -// start catch_config.hpp - -// start catch_test_spec_parser.h - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// start catch_test_spec.h - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// start catch_wildcard_pattern.h - -namespace Catch { -class WildcardPattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - -public: - WildcardPattern( - std::string const &pattern, CaseSensitive::Choice caseSensitivity); - virtual ~WildcardPattern() = default; - virtual bool matches(std::string const &str) const; - -private: - std::string normaliseString(std::string const &str) const; - CaseSensitive::Choice m_caseSensitivity; - WildcardPosition m_wildcard = NoWildcard; - std::string m_pattern; -}; -} - -// end catch_wildcard_pattern.h -#include -#include -#include - -namespace Catch { - -struct IConfig; - -class TestSpec { - class Pattern { - public: - explicit Pattern(std::string const &name); - virtual ~Pattern(); - virtual bool matches(TestCaseInfo const &testCase) const = 0; - std::string const &name() const; - - private: - std::string const m_name; - }; - using PatternPtr = std::shared_ptr; - - class NamePattern : public Pattern { - public: - explicit NamePattern( - std::string const &name, std::string const &filterString); - bool matches(TestCaseInfo const &testCase) const override; - - private: - WildcardPattern m_wildcardPattern; - }; - - class TagPattern : public Pattern { - public: - explicit TagPattern( - std::string const &tag, std::string const &filterString); - bool matches(TestCaseInfo const &testCase) const override; - - private: - std::string m_tag; - }; - - class ExcludedPattern : public Pattern { - public: - explicit ExcludedPattern(PatternPtr const &underlyingPattern); - bool matches(TestCaseInfo const &testCase) const override; - - private: - PatternPtr m_underlyingPattern; - }; - - struct Filter { - std::vector m_patterns; - - bool matches(TestCaseInfo const &testCase) const; - std::string name() const; - }; - -public: - struct FilterMatch { - std::string name; - std::vector tests; - }; - using Matches = std::vector; - using vectorStrings = std::vector; - - bool hasFilters() const; - bool matches(TestCaseInfo const &testCase) const; - Matches matchesByFilter( - std::vector const &testCases, IConfig const &config) const; - const vectorStrings &getInvalidArgs() const; - -private: - std::vector m_filters; - std::vector m_invalidArgs; - friend class TestSpecParser; -}; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// end catch_test_spec.h -// start catch_interfaces_tag_alias_registry.h - -#include - -namespace Catch { - -struct TagAlias; - -struct ITagAliasRegistry { - virtual ~ITagAliasRegistry(); - // Nullptr if not present - virtual TagAlias const *find(std::string const &alias) const = 0; - virtual std::string expandAliases( - std::string const &unexpandedTestSpec) const = 0; - - static ITagAliasRegistry const &get(); -}; - -} // end namespace Catch - -// end catch_interfaces_tag_alias_registry.h -namespace Catch { - -class TestSpecParser { - enum Mode { None, Name, QuotedName, Tag, EscapedName }; - Mode m_mode = None; - Mode lastMode = None; - bool m_exclusion = false; - std::size_t m_pos = 0; - std::size_t m_realPatternPos = 0; - std::string m_arg; - std::string m_substring; - std::string m_patternName; - std::vector m_escapeChars; - TestSpec::Filter m_currentFilter; - TestSpec m_testSpec; - ITagAliasRegistry const *m_tagAliases = nullptr; - -public: - TestSpecParser(ITagAliasRegistry const &tagAliases); - - TestSpecParser &parse(std::string const &arg); - TestSpec testSpec(); - -private: - bool visitChar(char c); - void startNewMode(Mode mode); - bool processNoneChar(char c); - void processNameChar(char c); - bool processOtherChar(char c); - void endMode(); - void escape(); - bool isControlChar(char c) const; - void saveLastMode(); - void revertBackToLastMode(); - void addFilter(); - bool separate(); - - // Handles common preprocessing of the pattern for name/tag patterns - std::string preprocessPattern(); - // Adds the current pattern as a test name - void addNamePattern(); - // Adds the current pattern as a tag - void addTagPattern(); - - inline void addCharToPattern(char c) - { - m_substring += c; - m_patternName += c; - m_realPatternPos++; - } -}; -TestSpec parseTestSpec(std::string const &arg); - -} // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// end catch_test_spec_parser.h -// Libstdc++ doesn't like incomplete classes for unique_ptr - -#include -#include -#include - -#ifndef CATCH_CONFIG_CONSOLE_WIDTH -#define CATCH_CONFIG_CONSOLE_WIDTH 80 -#endif - -namespace Catch { - -struct IStream; - -struct ConfigData { - bool listTests = false; - bool listTags = false; - bool listReporters = false; - bool listTestNamesOnly = false; - - bool showSuccessfulTests = false; - bool shouldDebugBreak = false; - bool noThrow = false; - bool showHelp = false; - bool showInvisibles = false; - bool filenamesAsTags = false; - bool libIdentify = false; - - int abortAfter = -1; - unsigned int rngSeed = 0; - - bool benchmarkNoAnalysis = false; - unsigned int benchmarkSamples = 100; - double benchmarkConfidenceInterval = 0.95; - unsigned int benchmarkResamples = 100000; - std::chrono::milliseconds::rep benchmarkWarmupTime = 100; - - Verbosity verbosity = Verbosity::Normal; - WarnAbout::What warnings = WarnAbout::Nothing; - ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; - double minDuration = -1; - RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; - UseColour::YesOrNo useColour = UseColour::Auto; - WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; - - std::string outputFilename; - std::string name; - std::string processName; -#ifndef CATCH_CONFIG_DEFAULT_REPORTER -#define CATCH_CONFIG_DEFAULT_REPORTER "console" -#endif - std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; -#undef CATCH_CONFIG_DEFAULT_REPORTER - - std::vector testsOrTags; - std::vector sectionsToRun; -}; - -class Config : public IConfig { -public: - Config() = default; - Config(ConfigData const &data); - virtual ~Config() = default; - - std::string const &getFilename() const; - - bool listTests() const; - bool listTestNamesOnly() const; - bool listTags() const; - bool listReporters() const; - - std::string getProcessName() const; - std::string const &getReporterName() const; - - std::vector const &getTestsOrTags() const override; - std::vector const &getSectionsToRun() const override; - - TestSpec const &testSpec() const override; - bool hasTestFilters() const override; - - bool showHelp() const; - - // IConfig interface - bool allowThrows() const override; - std::ostream &stream() const override; - std::string name() const override; - bool includeSuccessfulResults() const override; - bool warnAboutMissingAssertions() const override; - bool warnAboutNoTests() const override; - ShowDurations::OrNot showDurations() const override; - double minDuration() const override; - RunTests::InWhatOrder runOrder() const override; - unsigned int rngSeed() const override; - UseColour::YesOrNo useColour() const override; - bool shouldDebugBreak() const override; - int abortAfter() const override; - bool showInvisibles() const override; - Verbosity verbosity() const override; - bool benchmarkNoAnalysis() const override; - int benchmarkSamples() const override; - double benchmarkConfidenceInterval() const override; - unsigned int benchmarkResamples() const override; - std::chrono::milliseconds benchmarkWarmupTime() const override; - -private: - IStream const *openStream(); - ConfigData m_data; - - std::unique_ptr m_stream; - TestSpec m_testSpec; - bool m_hasTestFilters = false; -}; - -} // end namespace Catch - -// end catch_config.hpp -// start catch_assertionresult.h - -#include - -namespace Catch { - -struct AssertionResultData { - AssertionResultData() = delete; - - AssertionResultData( - ResultWas::OfType _resultType, LazyExpression const &_lazyExpression); - - std::string message; - mutable std::string reconstructedExpression; - LazyExpression lazyExpression; - ResultWas::OfType resultType; - - std::string reconstructExpression() const; -}; - -class AssertionResult { -public: - AssertionResult() = delete; - AssertionResult(AssertionInfo const &info, AssertionResultData const &data); - - bool isOk() const; - bool succeeded() const; - ResultWas::OfType getResultType() const; - bool hasExpression() const; - bool hasMessage() const; - std::string getExpression() const; - std::string getExpressionInMacro() const; - bool hasExpandedExpression() const; - std::string getExpandedExpression() const; - std::string getMessage() const; - SourceLineInfo getSourceInfo() const; - StringRef getTestMacroName() const; - - // protected: - AssertionInfo m_info; - AssertionResultData m_resultData; -}; - -} // end namespace Catch - -// end catch_assertionresult.h -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -// start catch_estimate.hpp - -// Statistics estimates - -namespace Catch { -namespace Benchmark { -template struct Estimate { - Duration point; - Duration lower_bound; - Duration upper_bound; - double confidence_interval; - - template operator Estimate() const - { - return {point, lower_bound, upper_bound, confidence_interval}; - } -}; -} // namespace Benchmark -} // namespace Catch - -// end catch_estimate.hpp -// start catch_outlier_classification.hpp - -// Outlier information - -namespace Catch { -namespace Benchmark { -struct OutlierClassification { - int samples_seen = 0; - int low_severe = 0; // more than 3 times IQR below Q1 - int low_mild = 0; // 1.5 to 3 times IQR below Q1 - int high_mild = 0; // 1.5 to 3 times IQR above Q3 - int high_severe = 0; // more than 3 times IQR above Q3 - - int total() const - { - return low_severe + low_mild + high_mild + high_severe; - } -}; -} // namespace Benchmark -} // namespace Catch - -// end catch_outlier_classification.hpp - -#include -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - -#include -#include -#include -#include -#include -#include - -namespace Catch { - -struct ReporterConfig { - explicit ReporterConfig(IConfigPtr const &_fullConfig); - - ReporterConfig(IConfigPtr const &_fullConfig, std::ostream &_stream); - - std::ostream &stream() const; - IConfigPtr fullConfig() const; - -private: - std::ostream *m_stream; - IConfigPtr m_fullConfig; -}; - -struct ReporterPreferences { - bool shouldRedirectStdOut = false; - bool shouldReportAllAssertions = false; -}; - -template struct LazyStat : Option { - LazyStat &operator=(T const &_value) - { - Option::operator=(_value); - used = false; - return *this; - } - void reset() - { - Option::reset(); - used = false; - } - bool used = false; -}; - -struct TestRunInfo { - TestRunInfo(std::string const &_name); - std::string name; -}; -struct GroupInfo { - GroupInfo(std::string const &_name, std::size_t _groupIndex, - std::size_t _groupsCount); - - std::string name; - std::size_t groupIndex; - std::size_t groupsCounts; -}; - -struct AssertionStats { - AssertionStats(AssertionResult const &_assertionResult, - std::vector const &_infoMessages, Totals const &_totals); - - AssertionStats(AssertionStats const &) = default; - AssertionStats(AssertionStats &&) = default; - AssertionStats &operator=(AssertionStats const &) = delete; - AssertionStats &operator=(AssertionStats &&) = delete; - virtual ~AssertionStats(); - - AssertionResult assertionResult; - std::vector infoMessages; - Totals totals; -}; - -struct SectionStats { - SectionStats(SectionInfo const &_sectionInfo, Counts const &_assertions, - double _durationInSeconds, bool _missingAssertions); - SectionStats(SectionStats const &) = default; - SectionStats(SectionStats &&) = default; - SectionStats &operator=(SectionStats const &) = default; - SectionStats &operator=(SectionStats &&) = default; - virtual ~SectionStats(); - - SectionInfo sectionInfo; - Counts assertions; - double durationInSeconds; - bool missingAssertions; -}; - -struct TestCaseStats { - TestCaseStats(TestCaseInfo const &_testInfo, Totals const &_totals, - std::string const &_stdOut, std::string const &_stdErr, bool _aborting); - - TestCaseStats(TestCaseStats const &) = default; - TestCaseStats(TestCaseStats &&) = default; - TestCaseStats &operator=(TestCaseStats const &) = default; - TestCaseStats &operator=(TestCaseStats &&) = default; - virtual ~TestCaseStats(); - - TestCaseInfo testInfo; - Totals totals; - std::string stdOut; - std::string stdErr; - bool aborting; -}; - -struct TestGroupStats { - TestGroupStats( - GroupInfo const &_groupInfo, Totals const &_totals, bool _aborting); - TestGroupStats(GroupInfo const &_groupInfo); - - TestGroupStats(TestGroupStats const &) = default; - TestGroupStats(TestGroupStats &&) = default; - TestGroupStats &operator=(TestGroupStats const &) = default; - TestGroupStats &operator=(TestGroupStats &&) = default; - virtual ~TestGroupStats(); - - GroupInfo groupInfo; - Totals totals; - bool aborting; -}; - -struct TestRunStats { - TestRunStats( - TestRunInfo const &_runInfo, Totals const &_totals, bool _aborting); - - TestRunStats(TestRunStats const &) = default; - TestRunStats(TestRunStats &&) = default; - TestRunStats &operator=(TestRunStats const &) = default; - TestRunStats &operator=(TestRunStats &&) = default; - virtual ~TestRunStats(); - - TestRunInfo runInfo; - Totals totals; - bool aborting; -}; - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -struct BenchmarkInfo { - std::string name; - double estimatedDuration; - int iterations; - int samples; - unsigned int resamples; - double clockResolution; - double clockCost; -}; - -template struct BenchmarkStats { - BenchmarkInfo info; - - std::vector samples; - Benchmark::Estimate mean; - Benchmark::Estimate standardDeviation; - Benchmark::OutlierClassification outliers; - double outlierVariance; - - template operator BenchmarkStats() const - { - std::vector samples2; - samples2.reserve(samples.size()); - std::transform(samples.begin(), samples.end(), - std::back_inserter(samples2), - [](Duration d) { return Duration2(d); }); - return { - info, - std::move(samples2), - mean, - standardDeviation, - outliers, - outlierVariance, - }; - } -}; -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - -struct IStreamingReporter { - virtual ~IStreamingReporter() = default; - - // Implementing class must also provide the following static methods: - // static std::string getDescription(); - // static std::set getSupportedVerbosities() - - virtual ReporterPreferences getPreferences() const = 0; - - virtual void noMatchingTestCases(std::string const &spec) = 0; - - virtual void reportInvalidArguments(std::string const &) { } - - virtual void testRunStarting(TestRunInfo const &testRunInfo) = 0; - virtual void testGroupStarting(GroupInfo const &groupInfo) = 0; - - virtual void testCaseStarting(TestCaseInfo const &testInfo) = 0; - virtual void sectionStarting(SectionInfo const §ionInfo) = 0; - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) - virtual void benchmarkPreparing(std::string const &) { } - virtual void benchmarkStarting(BenchmarkInfo const &) { } - virtual void benchmarkEnded(BenchmarkStats<> const &) { } - virtual void benchmarkFailed(std::string const &) { } -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - - virtual void assertionStarting(AssertionInfo const &assertionInfo) = 0; - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded(AssertionStats const &assertionStats) = 0; - - virtual void sectionEnded(SectionStats const §ionStats) = 0; - virtual void testCaseEnded(TestCaseStats const &testCaseStats) = 0; - virtual void testGroupEnded(TestGroupStats const &testGroupStats) = 0; - virtual void testRunEnded(TestRunStats const &testRunStats) = 0; - - virtual void skipTest(TestCaseInfo const &testInfo) = 0; - - // Default empty implementation provided - virtual void fatalErrorEncountered(StringRef name); - - virtual bool isMulti() const; -}; -using IStreamingReporterPtr = std::unique_ptr; - -struct IReporterFactory { - virtual ~IReporterFactory(); - virtual IStreamingReporterPtr create( - ReporterConfig const &config) const = 0; - virtual std::string getDescription() const = 0; -}; -using IReporterFactoryPtr = std::shared_ptr; - -struct IReporterRegistry { - using FactoryMap = std::map; - using Listeners = std::vector; - - virtual ~IReporterRegistry(); - virtual IStreamingReporterPtr create( - std::string const &name, IConfigPtr const &config) const = 0; - virtual FactoryMap const &getFactories() const = 0; - virtual Listeners const &getListeners() const = 0; -}; - -} // end namespace Catch - -// end catch_interfaces_reporter.h -#include -#include -#include -#include -#include -#include -#include - -namespace Catch { -void prepareExpandedExpression(AssertionResult &result); - -// Returns double formatted as %.3f (format expected on output) -std::string getFormattedDuration(double duration); - -//! Should the reporter show -bool shouldShowDuration(IConfig const &config, double duration); - -std::string serializeFilters(std::vector const &container); - -template struct StreamingReporterBase : IStreamingReporter { - - StreamingReporterBase(ReporterConfig const &_config) - : m_config(_config.fullConfig()) - , stream(_config.stream()) - { - m_reporterPrefs.shouldRedirectStdOut = false; - if (!DerivedT::getSupportedVerbosities().count(m_config->verbosity())) - CATCH_ERROR("Verbosity level not supported by this reporter"); - } - - ReporterPreferences getPreferences() const override - { - return m_reporterPrefs; - } - - static std::set getSupportedVerbosities() - { - return {Verbosity::Normal}; - } - - ~StreamingReporterBase() override = default; - - void noMatchingTestCases(std::string const &) override { } - - void reportInvalidArguments(std::string const &) override { } - - void testRunStarting(TestRunInfo const &_testRunInfo) override - { - currentTestRunInfo = _testRunInfo; - } - - void testGroupStarting(GroupInfo const &_groupInfo) override - { - currentGroupInfo = _groupInfo; - } - - void testCaseStarting(TestCaseInfo const &_testInfo) override - { - currentTestCaseInfo = _testInfo; - } - void sectionStarting(SectionInfo const &_sectionInfo) override - { - m_sectionStack.push_back(_sectionInfo); - } - - void sectionEnded(SectionStats const & /* _sectionStats */) override - { - m_sectionStack.pop_back(); - } - void testCaseEnded(TestCaseStats const & /* _testCaseStats */) override - { - currentTestCaseInfo.reset(); - } - void testGroupEnded(TestGroupStats const & /* _testGroupStats */) override - { - currentGroupInfo.reset(); - } - void testRunEnded(TestRunStats const & /* _testRunStats */) override - { - currentTestCaseInfo.reset(); - currentGroupInfo.reset(); - currentTestRunInfo.reset(); - } - - void skipTest(TestCaseInfo const &) override - { - // Don't do anything with this by default. - // It can optionally be overridden in the derived class. - } - - IConfigPtr m_config; - std::ostream &stream; - - LazyStat currentTestRunInfo; - LazyStat currentGroupInfo; - LazyStat currentTestCaseInfo; - - std::vector m_sectionStack; - ReporterPreferences m_reporterPrefs; -}; - -template -struct CumulativeReporterBase : IStreamingReporter { - template struct Node { - explicit Node(T const &_value) - : value(_value) - { - } - virtual ~Node() { } - - using ChildNodes = std::vector>; - T value; - ChildNodes children; - }; - struct SectionNode { - explicit SectionNode(SectionStats const &_stats) - : stats(_stats) - { - } - virtual ~SectionNode() = default; - - bool operator==(SectionNode const &other) const - { - return stats.sectionInfo.lineInfo == - other.stats.sectionInfo.lineInfo; - } - bool operator==(std::shared_ptr const &other) const - { - return operator==(*other); - } - - SectionStats stats; - using ChildSections = std::vector>; - using Assertions = std::vector; - ChildSections childSections; - Assertions assertions; - std::string stdOut; - std::string stdErr; - }; - - struct BySectionInfo { - BySectionInfo(SectionInfo const &other) - : m_other(other) - { - } - BySectionInfo(BySectionInfo const &other) - : m_other(other.m_other) - { - } - bool operator()(std::shared_ptr const &node) const - { - return ((node->stats.sectionInfo.name == m_other.name) && - (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); - } - void operator=(BySectionInfo const &) = delete; - - private: - SectionInfo const &m_other; - }; - - using TestCaseNode = Node; - using TestGroupNode = Node; - using TestRunNode = Node; - - CumulativeReporterBase(ReporterConfig const &_config) - : m_config(_config.fullConfig()) - , stream(_config.stream()) - { - m_reporterPrefs.shouldRedirectStdOut = false; - if (!DerivedT::getSupportedVerbosities().count(m_config->verbosity())) - CATCH_ERROR("Verbosity level not supported by this reporter"); - } - ~CumulativeReporterBase() override = default; - - ReporterPreferences getPreferences() const override - { - return m_reporterPrefs; - } - - static std::set getSupportedVerbosities() - { - return {Verbosity::Normal}; - } - - void testRunStarting(TestRunInfo const &) override { } - void testGroupStarting(GroupInfo const &) override { } - - void testCaseStarting(TestCaseInfo const &) override { } - - void sectionStarting(SectionInfo const §ionInfo) override - { - SectionStats incompleteStats(sectionInfo, Counts(), 0, false); - std::shared_ptr node; - if (m_sectionStack.empty()) { - if (!m_rootSection) - m_rootSection = std::make_shared(incompleteStats); - node = m_rootSection; - } - else { - SectionNode &parentNode = *m_sectionStack.back(); - auto it = std::find_if(parentNode.childSections.begin(), - parentNode.childSections.end(), BySectionInfo(sectionInfo)); - if (it == parentNode.childSections.end()) { - node = std::make_shared(incompleteStats); - parentNode.childSections.push_back(node); - } - else - node = *it; - } - m_sectionStack.push_back(node); - m_deepestSection = std::move(node); - } - - void assertionStarting(AssertionInfo const &) override { } - - bool assertionEnded(AssertionStats const &assertionStats) override - { - assert(!m_sectionStack.empty()); - // AssertionResult holds a pointer to a temporary DecomposedExpression, - // which getExpandedExpression() calls to build the expression string. - // Our section stack copy of the assertionResult will likely outlive the - // temporary, so it must be expanded or discarded now to avoid calling - // a destroyed object later. - prepareExpandedExpression( - const_cast(assertionStats.assertionResult)); - SectionNode §ionNode = *m_sectionStack.back(); - sectionNode.assertions.push_back(assertionStats); - return true; - } - void sectionEnded(SectionStats const §ionStats) override - { - assert(!m_sectionStack.empty()); - SectionNode &node = *m_sectionStack.back(); - node.stats = sectionStats; - m_sectionStack.pop_back(); - } - void testCaseEnded(TestCaseStats const &testCaseStats) override - { - auto node = std::make_shared(testCaseStats); - assert(m_sectionStack.size() == 0); - node->children.push_back(m_rootSection); - m_testCases.push_back(node); - m_rootSection.reset(); - - assert(m_deepestSection); - m_deepestSection->stdOut = testCaseStats.stdOut; - m_deepestSection->stdErr = testCaseStats.stdErr; - } - void testGroupEnded(TestGroupStats const &testGroupStats) override - { - auto node = std::make_shared(testGroupStats); - node->children.swap(m_testCases); - m_testGroups.push_back(node); - } - void testRunEnded(TestRunStats const &testRunStats) override - { - auto node = std::make_shared(testRunStats); - node->children.swap(m_testGroups); - m_testRuns.push_back(node); - testRunEndedCumulative(); - } - virtual void testRunEndedCumulative() = 0; - - void skipTest(TestCaseInfo const &) override { } - - IConfigPtr m_config; - std::ostream &stream; - std::vector m_assertions; - std::vector>> m_sections; - std::vector> m_testCases; - std::vector> m_testGroups; - - std::vector> m_testRuns; - - std::shared_ptr m_rootSection; - std::shared_ptr m_deepestSection; - std::vector> m_sectionStack; - ReporterPreferences m_reporterPrefs; -}; - -template char const *getLineOfChars() -{ - static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; - if (!*line) { - std::memset(line, C, CATCH_CONFIG_CONSOLE_WIDTH - 1); - line[CATCH_CONFIG_CONSOLE_WIDTH - 1] = 0; - } - return line; -} - -struct TestEventListenerBase : StreamingReporterBase { - TestEventListenerBase(ReporterConfig const &_config); - - static std::set getSupportedVerbosities(); - - void assertionStarting(AssertionInfo const &) override; - bool assertionEnded(AssertionStats const &) override; -}; - -} // end namespace Catch - -// end catch_reporter_bases.hpp -// start catch_console_colour.h - -namespace Catch { - -struct Colour { - enum Code { - None = 0, - - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, - BrightYellow = Bright | Yellow, - - // By intention - FileName = LightGrey, - Warning = BrightYellow, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - ResultExpectedFailure = Warning, - - Error = BrightRed, - Success = Green, - - OriginalExpression = Cyan, - ReconstructedExpression = BrightYellow, - - SecondaryText = LightGrey, - Headers = White - }; - - // Use constructed object for RAII guard - Colour(Code _colourCode); - Colour(Colour &&other) noexcept; - Colour &operator=(Colour &&other) noexcept; - ~Colour(); - - // Use static method for one-shot changes - static void use(Code _colourCode); - -private: - bool m_moved = false; -}; - -std::ostream &operator<<(std::ostream &os, Colour const &); - -} // end namespace Catch - -// end catch_console_colour.h -// start catch_reporter_registrars.hpp - -namespace Catch { - -template class ReporterRegistrar { - - class ReporterFactory : public IReporterFactory { - - IStreamingReporterPtr create( - ReporterConfig const &config) const override - { - return std::unique_ptr(new T(config)); - } - - std::string getDescription() const override - { - return T::getDescription(); - } - }; - -public: - explicit ReporterRegistrar(std::string const &name) - { - getMutableRegistryHub().registerReporter( - name, std::make_shared()); - } -}; - -template class ListenerRegistrar { - - class ListenerFactory : public IReporterFactory { - - IStreamingReporterPtr create( - ReporterConfig const &config) const override - { - return std::unique_ptr(new T(config)); - } - std::string getDescription() const override { return std::string(); } - }; - -public: - ListenerRegistrar() - { - getMutableRegistryHub().registerListener( - std::make_shared()); - } -}; -} - -#if !defined(CATCH_CONFIG_DISABLE) - -#define CATCH_REGISTER_REPORTER(name, reporterType) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace { \ - Catch::ReporterRegistrar \ - catch_internal_RegistrarFor##reporterType(name); \ - } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - -#define CATCH_REGISTER_LISTENER(listenerType) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace { \ - Catch::ListenerRegistrar \ - catch_internal_RegistrarFor##listenerType; \ - } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION -#else // CATCH_CONFIG_DISABLE - -#define CATCH_REGISTER_REPORTER(name, reporterType) -#define CATCH_REGISTER_LISTENER(listenerType) - -#endif // CATCH_CONFIG_DISABLE - -// end catch_reporter_registrars.hpp -// Allow users to base their work off existing reporters -// start catch_reporter_compact.h - -namespace Catch { - -struct CompactReporter : StreamingReporterBase { - - using StreamingReporterBase::StreamingReporterBase; - - ~CompactReporter() override; - - static std::string getDescription(); - - void noMatchingTestCases(std::string const &spec) override; - - void assertionStarting(AssertionInfo const &) override; - - bool assertionEnded(AssertionStats const &_assertionStats) override; - - void sectionEnded(SectionStats const &_sectionStats) override; - - void testRunEnded(TestRunStats const &_testRunStats) override; -}; - -} // end namespace Catch - -// end catch_reporter_compact.h -// start catch_reporter_console.h - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4061) // Not all labels are EXPLICITLY handled in - // switch Note that 4062 (not all labels are - // handled and default is missing) is enabled -#endif - -namespace Catch { -// Fwd decls -struct SummaryColumn; -class TablePrinter; - -struct ConsoleReporter : StreamingReporterBase { - std::unique_ptr m_tablePrinter; - - ConsoleReporter(ReporterConfig const &config); - ~ConsoleReporter() override; - static std::string getDescription(); - - void noMatchingTestCases(std::string const &spec) override; - - void reportInvalidArguments(std::string const &arg) override; - - void assertionStarting(AssertionInfo const &) override; - - bool assertionEnded(AssertionStats const &_assertionStats) override; - - void sectionStarting(SectionInfo const &_sectionInfo) override; - void sectionEnded(SectionStats const &_sectionStats) override; - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) - void benchmarkPreparing(std::string const &name) override; - void benchmarkStarting(BenchmarkInfo const &info) override; - void benchmarkEnded(BenchmarkStats<> const &stats) override; - void benchmarkFailed(std::string const &error) override; -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - - void testCaseEnded(TestCaseStats const &_testCaseStats) override; - void testGroupEnded(TestGroupStats const &_testGroupStats) override; - void testRunEnded(TestRunStats const &_testRunStats) override; - void testRunStarting(TestRunInfo const &_testRunInfo) override; - -private: - void lazyPrint(); - - void lazyPrintWithoutClosingBenchmarkTable(); - void lazyPrintRunInfo(); - void lazyPrintGroupInfo(); - void printTestCaseAndSectionHeader(); - - void printClosedHeader(std::string const &_name); - void printOpenHeader(std::string const &_name); - - // if string has a : in first line will set indent to follow it on - // subsequent lines - void printHeaderString(std::string const &_string, std::size_t indent = 0); - - void printTotals(Totals const &totals); - void printSummaryRow(std::string const &label, - std::vector const &cols, std::size_t row); - - void printTotalsDivider(Totals const &totals); - void printSummaryDivider(); - void printTestFilters(); - -private: - bool m_headerPrinted = false; -}; - -} // end namespace Catch - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -// end catch_reporter_console.h -// start catch_reporter_junit.h - -// start catch_xmlwriter.h - -#include - -namespace Catch { -enum class XmlFormatting { - None = 0x00, - Indent = 0x01, - Newline = 0x02, -}; - -XmlFormatting operator|(XmlFormatting lhs, XmlFormatting rhs); -XmlFormatting operator&(XmlFormatting lhs, XmlFormatting rhs); - -class XmlEncode { -public: - enum ForWhat { ForTextNodes, ForAttributes }; - - XmlEncode(std::string const &str, ForWhat forWhat = ForTextNodes); - - void encodeTo(std::ostream &os) const; - - friend std::ostream &operator<<( - std::ostream &os, XmlEncode const &xmlEncode); - -private: - std::string m_str; - ForWhat m_forWhat; -}; - -class XmlWriter { -public: - class ScopedElement { - public: - ScopedElement(XmlWriter *writer, XmlFormatting fmt); - - ScopedElement(ScopedElement &&other) noexcept; - ScopedElement &operator=(ScopedElement &&other) noexcept; - - ~ScopedElement(); - - ScopedElement &writeText(std::string const &text, - XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); - - template - ScopedElement &writeAttribute( - std::string const &name, T const &attribute) - { - m_writer->writeAttribute(name, attribute); - return *this; - } - - private: - mutable XmlWriter *m_writer = nullptr; - XmlFormatting m_fmt; - }; - - XmlWriter(std::ostream &os = Catch::cout()); - ~XmlWriter(); - - XmlWriter(XmlWriter const &) = delete; - XmlWriter &operator=(XmlWriter const &) = delete; - - XmlWriter &startElement(std::string const &name, - XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); - - ScopedElement scopedElement(std::string const &name, - XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); - - XmlWriter &endElement( - XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); - - XmlWriter &writeAttribute( - std::string const &name, std::string const &attribute); - - XmlWriter &writeAttribute(std::string const &name, bool attribute); - - template - XmlWriter &writeAttribute(std::string const &name, T const &attribute) - { - ReusableStringStream rss; - rss << attribute; - return writeAttribute(name, rss.str()); - } - - XmlWriter &writeText(std::string const &text, - XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); - - XmlWriter &writeComment(std::string const &text, - XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); - - void writeStylesheetRef(std::string const &url); - - XmlWriter &writeBlankLine(); - - void ensureTagClosed(); - -private: - void applyFormatting(XmlFormatting fmt); - - void writeDeclaration(); - - void newlineIfNecessary(); - - bool m_tagIsOpen = false; - bool m_needsNewline = false; - std::vector m_tags; - std::string m_indent; - std::ostream &m_os; -}; - -} - -// end catch_xmlwriter.h -namespace Catch { - -class JunitReporter : public CumulativeReporterBase { -public: - JunitReporter(ReporterConfig const &_config); - - ~JunitReporter() override; - - static std::string getDescription(); - - void noMatchingTestCases(std::string const & /*spec*/) override; - - void testRunStarting(TestRunInfo const &runInfo) override; - - void testGroupStarting(GroupInfo const &groupInfo) override; - - void testCaseStarting(TestCaseInfo const &testCaseInfo) override; - bool assertionEnded(AssertionStats const &assertionStats) override; - - void testCaseEnded(TestCaseStats const &testCaseStats) override; - - void testGroupEnded(TestGroupStats const &testGroupStats) override; - - void testRunEndedCumulative() override; - - void writeGroup(TestGroupNode const &groupNode, double suiteTime); - - void writeTestCase(TestCaseNode const &testCaseNode); - - void writeSection(std::string const &className, std::string const &rootName, - SectionNode const §ionNode, bool testOkToFail); - - void writeAssertions(SectionNode const §ionNode); - void writeAssertion(AssertionStats const &stats); - - XmlWriter xml; - Timer suiteTimer; - std::string stdOutForSuite; - std::string stdErrForSuite; - unsigned int unexpectedExceptions = 0; - bool m_okToFail = false; -}; - -} // end namespace Catch - -// end catch_reporter_junit.h -// start catch_reporter_xml.h - -namespace Catch { -class XmlReporter : public StreamingReporterBase { -public: - XmlReporter(ReporterConfig const &_config); - - ~XmlReporter() override; - - static std::string getDescription(); - - virtual std::string getStylesheetRef() const; - - void writeSourceInfo(SourceLineInfo const &sourceInfo); - -public: // StreamingReporterBase - void noMatchingTestCases(std::string const &s) override; - - void testRunStarting(TestRunInfo const &testInfo) override; - - void testGroupStarting(GroupInfo const &groupInfo) override; - - void testCaseStarting(TestCaseInfo const &testInfo) override; - - void sectionStarting(SectionInfo const §ionInfo) override; - - void assertionStarting(AssertionInfo const &) override; - - bool assertionEnded(AssertionStats const &assertionStats) override; - - void sectionEnded(SectionStats const §ionStats) override; - - void testCaseEnded(TestCaseStats const &testCaseStats) override; - - void testGroupEnded(TestGroupStats const &testGroupStats) override; - - void testRunEnded(TestRunStats const &testRunStats) override; - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) - void benchmarkPreparing(std::string const &name) override; - void benchmarkStarting(BenchmarkInfo const &) override; - void benchmarkEnded(BenchmarkStats<> const &) override; - void benchmarkFailed(std::string const &) override; -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - -private: - Timer m_testCaseTimer; - XmlWriter m_xml; - int m_sectionDepth = 0; -}; - -} // end namespace Catch - -// end catch_reporter_xml.h - -// end catch_external_interfaces.h -#endif - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -// start catch_benchmarking_all.hpp - -// A proxy header that includes all of the benchmarking headers to allow -// concise include of the benchmarking features. You should prefer the -// individual includes in standard use. - -// start catch_benchmark.hpp - -// Benchmark - -// start catch_chronometer.hpp - -// User-facing chronometer - -// start catch_clock.hpp - -// Clocks - -#include -#include - -namespace Catch { -namespace Benchmark { -template using ClockDuration = typename Clock::duration; -template -using FloatDuration = std::chrono::duration; - -template using TimePoint = typename Clock::time_point; - -using default_clock = std::chrono::steady_clock; - -template struct now { - TimePoint operator()() const { return Clock::now(); } -}; - -using fp_seconds = std::chrono::duration>; -} // namespace Benchmark -} // namespace Catch - -// end catch_clock.hpp -// start catch_optimizer.hpp - -// Hinting the optimizer - -#if defined(_MSC_VER) -#include // atomic_thread_fence -#endif - -namespace Catch { -namespace Benchmark { -#if defined(__GNUC__) || defined(__clang__) -template inline void keep_memory(T *p) -{ - asm volatile("" : : "g"(p) : "memory"); -} -inline void keep_memory() { asm volatile("" : : : "memory"); } - -namespace Detail { -inline void optimizer_barrier() { keep_memory(); } -} // namespace Detail -#elif defined(_MSC_VER) - -#pragma optimize("", off) -template inline void keep_memory(T *p) -{ - // thanks @milleniumbug - *reinterpret_cast(p) = - *reinterpret_cast(p); -} -// TODO equivalent keep_memory() -#pragma optimize("", on) - -namespace Detail { -inline void optimizer_barrier() -{ - std::atomic_thread_fence(std::memory_order_seq_cst); -} -} // namespace Detail - -#endif - -template inline void deoptimize_value(T &&x) { keep_memory(&x); } - -template -inline auto invoke_deoptimized(Fn &&fn, Args &&...args) -> - typename std::enable_if< - !std::is_same::value>::type -{ - deoptimize_value(std::forward(fn)(std::forward(args...))); -} - -template -inline auto invoke_deoptimized(Fn &&fn, Args &&...args) -> - typename std::enable_if< - std::is_same::value>::type -{ - std::forward(fn)(std::forward(args...)); -} -} // namespace Benchmark -} // namespace Catch - -// end catch_optimizer.hpp -// start catch_complete_invoke.hpp - -// Invoke with a special case for void - -#include -#include - -namespace Catch { -namespace Benchmark { -namespace Detail { -template struct CompleteType { - using type = T; -}; -template <> struct CompleteType { - struct type { }; -}; - -template using CompleteType_t = typename CompleteType::type; - -template struct CompleteInvoker { - template - static Result invoke(Fun &&fun, Args &&...args) - { - return std::forward(fun)(std::forward(args)...); - } -}; -template <> struct CompleteInvoker { - template - static CompleteType_t invoke(Fun &&fun, Args &&...args) - { - std::forward(fun)(std::forward(args)...); - return {}; - } -}; - -// invoke and not return void :( -template -CompleteType_t> complete_invoke( - Fun &&fun, Args &&...args) -{ - return CompleteInvoker>::invoke( - std::forward(fun), std::forward(args)...); -} - -const std::string benchmarkErrorMsg = "a benchmark failed to run successfully"; -} // namespace Detail - -template -Detail::CompleteType_t> user_code(Fun &&fun) -{ - CATCH_TRY { return Detail::complete_invoke(std::forward(fun)); } - CATCH_CATCH_ALL - { - getResultCapture().benchmarkFailed(translateActiveException()); - CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg); - } -} -} // namespace Benchmark -} // namespace Catch - -// end catch_complete_invoke.hpp -namespace Catch { -namespace Benchmark { -namespace Detail { -struct ChronometerConcept { - virtual void start() = 0; - virtual void finish() = 0; - virtual ~ChronometerConcept() = default; -}; -template -struct ChronometerModel final : public ChronometerConcept { - void start() override { started = Clock::now(); } - void finish() override { finished = Clock::now(); } - - ClockDuration elapsed() const { return finished - started; } - - TimePoint started; - TimePoint finished; -}; -} // namespace Detail - -struct Chronometer { -public: - template void measure(Fun &&fun) - { - measure(std::forward(fun), is_callable()); - } - - int runs() const { return k; } - - Chronometer(Detail::ChronometerConcept &meter, int k) - : impl(&meter) - , k(k) - { - } - -private: - template void measure(Fun &&fun, std::false_type) - { - measure([&fun](int) { return fun(); }, std::true_type()); - } - - template void measure(Fun &&fun, std::true_type) - { - Detail::optimizer_barrier(); - impl->start(); - for (int i = 0; i < k; ++i) - invoke_deoptimized(fun, i); - impl->finish(); - Detail::optimizer_barrier(); - } - - Detail::ChronometerConcept *impl; - int k; -}; -} // namespace Benchmark -} // namespace Catch - -// end catch_chronometer.hpp -// start catch_environment.hpp - -// Environment information - -namespace Catch { -namespace Benchmark { -template struct EnvironmentEstimate { - Duration mean; - OutlierClassification outliers; - - template - operator EnvironmentEstimate() const - { - return {mean, outliers}; - } -}; -template struct Environment { - using clock_type = Clock; - EnvironmentEstimate> clock_resolution; - EnvironmentEstimate> clock_cost; -}; -} // namespace Benchmark -} // namespace Catch - -// end catch_environment.hpp -// start catch_execution_plan.hpp - -// Execution plan - -// start catch_benchmark_function.hpp - -// Dumb std::function implementation for consistent call overhead - -#include -#include -#include -#include - -namespace Catch { -namespace Benchmark { -namespace Detail { -template using Decay = typename std::decay::type; -template -struct is_related : std::is_same, Decay> { }; - -/// We need to reinvent std::function because every piece of code that might add -/// overhead in a measurement context needs to have consistent performance -/// characteristics so that we can account for it in the measurement. -/// Implementations of std::function with optimizations that aren't always -/// applicable, like small buffer optimizations, are not uncommon. This is -/// effectively an implementation of std::function without any such -/// optimizations; it may be slow, but it is consistently slow. -struct BenchmarkFunction { -private: - struct callable { - virtual void call(Chronometer meter) const = 0; - virtual callable *clone() const = 0; - virtual ~callable() = default; - }; - template struct model : public callable { - model(Fun &&fun) - : fun(std::move(fun)) - { - } - model(Fun const &fun) - : fun(fun) - { - } - - model *clone() const override { return new model(*this); } - - void call(Chronometer meter) const override - { - call(meter, is_callable()); - } - void call(Chronometer meter, std::true_type) const { fun(meter); } - void call(Chronometer meter, std::false_type) const - { - meter.measure(fun); - } - - Fun fun; - }; - - struct do_nothing { - void operator()() const { } - }; - - template - BenchmarkFunction(model *c) - : f(c) - { - } - -public: - BenchmarkFunction() - : f(new model{{}}) - { - } - - template ::value, - int>::type = 0> - BenchmarkFunction(Fun &&fun) - : f(new model::type>(std::forward(fun))) - { - } - - BenchmarkFunction(BenchmarkFunction &&that) - : f(std::move(that.f)) - { - } - - BenchmarkFunction(BenchmarkFunction const &that) - : f(that.f->clone()) - { - } - - BenchmarkFunction &operator=(BenchmarkFunction &&that) - { - f = std::move(that.f); - return *this; - } - - BenchmarkFunction &operator=(BenchmarkFunction const &that) - { - f.reset(that.f->clone()); - return *this; - } - - void operator()(Chronometer meter) const { f->call(meter); } - -private: - std::unique_ptr f; -}; -} // namespace Detail -} // namespace Benchmark -} // namespace Catch - -// end catch_benchmark_function.hpp -// start catch_repeat.hpp - -// repeat algorithm - -#include -#include - -namespace Catch { -namespace Benchmark { -namespace Detail { -template struct repeater { - void operator()(int k) const - { - for (int i = 0; i < k; ++i) { - fun(); - } - } - Fun fun; -}; -template -repeater::type> repeat(Fun &&fun) -{ - return {std::forward(fun)}; -} -} // namespace Detail -} // namespace Benchmark -} // namespace Catch - -// end catch_repeat.hpp -// start catch_run_for_at_least.hpp - -// Run a function for a minimum amount of time - -// start catch_measure.hpp - -// Measure - -// start catch_timing.hpp - -// Timing - -#include -#include - -namespace Catch { -namespace Benchmark { -template struct Timing { - Duration elapsed; - Result result; - int iterations; -}; -template -using TimingOf = Timing, - Detail::CompleteType_t>>; -} // namespace Benchmark -} // namespace Catch - -// end catch_timing.hpp -#include - -namespace Catch { -namespace Benchmark { -namespace Detail { -template -TimingOf measure(Fun &&fun, Args &&...args) -{ - auto start = Clock::now(); - auto &&r = Detail::complete_invoke(fun, std::forward(args)...); - auto end = Clock::now(); - auto delta = end - start; - return {delta, std::forward(r), 1}; -} -} // namespace Detail -} // namespace Benchmark -} // namespace Catch - -// end catch_measure.hpp -#include -#include - -namespace Catch { -namespace Benchmark { -namespace Detail { -template -TimingOf measure_one(Fun &&fun, int iters, std::false_type) -{ - return Detail::measure(fun, iters); -} -template -TimingOf measure_one( - Fun &&fun, int iters, std::true_type) -{ - Detail::ChronometerModel meter; - auto &&result = Detail::complete_invoke(fun, Chronometer(meter, iters)); - - return {meter.elapsed(), std::move(result), iters}; -} - -template -using run_for_at_least_argument_t = - typename std::conditional::value, Chronometer, - int>::type; - -struct optimized_away_error : std::exception { - const char *what() const noexcept override - { - return "could not measure benchmark, maybe it was optimized away"; - } -}; - -template -TimingOf> run_for_at_least( - ClockDuration how_long, int seed, Fun &&fun) -{ - auto iters = seed; - while (iters < (1 << 30)) { - auto &&Timing = - measure_one(fun, iters, is_callable()); - - if (Timing.elapsed >= how_long) { - return {Timing.elapsed, std::move(Timing.result), iters}; - } - iters *= 2; - } - Catch::throw_exception(optimized_away_error{}); -} -} // namespace Detail -} // namespace Benchmark -} // namespace Catch - -// end catch_run_for_at_least.hpp -#include -#include - -namespace Catch { -namespace Benchmark { -template struct ExecutionPlan { - int iterations_per_sample; - Duration estimated_duration; - Detail::BenchmarkFunction benchmark; - Duration warmup_time; - int warmup_iterations; - - template operator ExecutionPlan() const - { - return {iterations_per_sample, estimated_duration, benchmark, - warmup_time, warmup_iterations}; - } - - template - std::vector> run( - const IConfig &cfg, Environment> env) const - { - // warmup a bit - Detail::run_for_at_least( - std::chrono::duration_cast>(warmup_time), - warmup_iterations, Detail::repeat(now{})); - - std::vector> times; - times.reserve(cfg.benchmarkSamples()); - std::generate_n( - std::back_inserter(times), cfg.benchmarkSamples(), [this, env] { - Detail::ChronometerModel model; - this->benchmark(Chronometer(model, iterations_per_sample)); - auto sample_time = model.elapsed() - env.clock_cost.mean; - if (sample_time < FloatDuration::zero()) - sample_time = FloatDuration::zero(); - return sample_time / iterations_per_sample; - }); - return times; - } -}; -} // namespace Benchmark -} // namespace Catch - -// end catch_execution_plan.hpp -// start catch_estimate_clock.hpp - -// Environment measurement - -// start catch_stats.hpp - -// Statistical analysis tools - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Catch { -namespace Benchmark { -namespace Detail { -using sample = std::vector; - -double weighted_average_quantile(int k, int q, - std::vector::iterator first, std::vector::iterator last); - -template -OutlierClassification classify_outliers(Iterator first, Iterator last) -{ - std::vector copy(first, last); - - auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end()); - auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end()); - auto iqr = q3 - q1; - auto los = q1 - (iqr * 3.); - auto lom = q1 - (iqr * 1.5); - auto him = q3 + (iqr * 1.5); - auto his = q3 + (iqr * 3.); - - OutlierClassification o; - for (; first != last; ++first) { - auto &&t = *first; - if (t < los) - ++o.low_severe; - else if (t < lom) - ++o.low_mild; - else if (t > his) - ++o.high_severe; - else if (t > him) - ++o.high_mild; - ++o.samples_seen; - } - return o; -} - -template double mean(Iterator first, Iterator last) -{ - auto count = last - first; - double sum = std::accumulate(first, last, 0.); - return sum / count; -} - -template -sample resample(URng &rng, int resamples, Iterator first, Iterator last, - Estimator &estimator) -{ - auto n = last - first; - std::uniform_int_distribution dist(0, n - 1); - - sample out; - out.reserve(resamples); - std::generate_n(std::back_inserter(out), resamples, - [n, first, &estimator, &dist, &rng] { - std::vector resampled; - resampled.reserve(n); - std::generate_n(std::back_inserter(resampled), n, - [first, &dist, &rng] { return first[dist(rng)]; }); - return estimator(resampled.begin(), resampled.end()); - }); - std::sort(out.begin(), out.end()); - return out; -} - -template -sample jackknife(Estimator &&estimator, Iterator first, Iterator last) -{ - auto n = last - first; - auto second = std::next(first); - sample results; - results.reserve(n); - - for (auto it = first; it != last; ++it) { - std::iter_swap(it, first); - results.push_back(estimator(second, last)); - } - - return results; -} - -inline double normal_cdf(double x) -{ - return std::erfc(-x / std::sqrt(2.0)) / 2.0; -} - -double erfc_inv(double x); - -double normal_quantile(double p); - -template -Estimate bootstrap(double confidence_level, Iterator first, - Iterator last, sample const &resample, Estimator &&estimator) -{ - auto n_samples = last - first; - - double point = estimator(first, last); - // Degenerate case with a single sample - if (n_samples == 1) - return {point, point, point, confidence_level}; - - sample jack = jackknife(estimator, first, last); - double jack_mean = mean(jack.begin(), jack.end()); - double sum_squares, sum_cubes; - std::tie(sum_squares, sum_cubes) = - std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.), - [jack_mean](std::pair sqcb, - double x) -> std::pair { - auto d = jack_mean - x; - auto d2 = d * d; - auto d3 = d2 * d; - return {sqcb.first + d2, sqcb.second + d3}; - }); - - double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5)); - int n = static_cast(resample.size()); - double prob_n = std::count_if(resample.begin(), resample.end(), - [point](double x) { return x < point; }) / - (double)n; - // degenerate case with uniform samples - if (prob_n == 0) - return {point, point, point, confidence_level}; - - double bias = normal_quantile(prob_n); - double z1 = normal_quantile((1. - confidence_level) / 2.); - - auto cumn = [n](double x) -> int { return std::lround(normal_cdf(x) * n); }; - auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); }; - double b1 = bias + z1; - double b2 = bias - z1; - double a1 = a(b1); - double a2 = a(b2); - auto lo = (std::max)(cumn(a1), 0); - auto hi = (std::min)(cumn(a2), n - 1); - - return {point, resample[lo], resample[hi], confidence_level}; -} - -double outlier_variance(Estimate mean, Estimate stddev, int n); - -struct bootstrap_analysis { - Estimate mean; - Estimate standard_deviation; - double outlier_variance; -}; - -bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, - std::vector::iterator first, std::vector::iterator last); -} // namespace Detail -} // namespace Benchmark -} // namespace Catch - -// end catch_stats.hpp -#include -#include -#include -#include -#include - -namespace Catch { -namespace Benchmark { -namespace Detail { -template std::vector resolution(int k) -{ - std::vector> times; - times.reserve(k + 1); - std::generate_n(std::back_inserter(times), k + 1, now{}); - - std::vector deltas; - deltas.reserve(k); - std::transform(std::next(times.begin()), times.end(), times.begin(), - std::back_inserter(deltas), [](TimePoint a, TimePoint b) { - return static_cast((a - b).count()); - }); - - return deltas; -} - -const auto warmup_iterations = 10000; -const auto warmup_time = std::chrono::milliseconds(100); -const auto minimum_ticks = 1000; -const auto warmup_seed = 10000; -const auto clock_resolution_estimation_time = std::chrono::milliseconds(500); -const auto clock_cost_estimation_time_limit = std::chrono::seconds(1); -const auto clock_cost_estimation_tick_limit = 100000; -const auto clock_cost_estimation_time = std::chrono::milliseconds(10); -const auto clock_cost_estimation_iterations = 10000; - -template int warmup() -{ - return run_for_at_least( - std::chrono::duration_cast>(warmup_time), - warmup_seed, &resolution) - .iterations; -} -template -EnvironmentEstimate> estimate_clock_resolution( - int iterations) -{ - auto r = run_for_at_least( - std::chrono::duration_cast>( - clock_resolution_estimation_time), - iterations, &resolution) - .result; - return { - FloatDuration(mean(r.begin(), r.end())), - classify_outliers(r.begin(), r.end()), - }; -} -template -EnvironmentEstimate> estimate_clock_cost( - FloatDuration resolution) -{ - auto time_limit = (std::min)(resolution * clock_cost_estimation_tick_limit, - FloatDuration(clock_cost_estimation_time_limit)); - auto time_clock = [](int k) { - return Detail::measure([k] { - for (int i = 0; i < k; ++i) { - volatile auto ignored = Clock::now(); - (void)ignored; - } - }).elapsed; - }; - time_clock(1); - int iters = clock_cost_estimation_iterations; - auto &&r = run_for_at_least( - std::chrono::duration_cast>( - clock_cost_estimation_time), - iters, time_clock); - std::vector times; - int nsamples = static_cast(std::ceil(time_limit / r.elapsed)); - times.reserve(nsamples); - std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] { - return static_cast( - (time_clock(r.iterations) / r.iterations).count()); - }); - return { - FloatDuration(mean(times.begin(), times.end())), - classify_outliers(times.begin(), times.end()), - }; -} - -template -Environment> measure_environment() -{ - static Environment> *env = nullptr; - if (env) { - return *env; - } - - auto iters = Detail::warmup(); - auto resolution = Detail::estimate_clock_resolution(iters); - auto cost = Detail::estimate_clock_cost(resolution.mean); - - env = new Environment>{resolution, cost}; - return *env; -} -} // namespace Detail -} // namespace Benchmark -} // namespace Catch - -// end catch_estimate_clock.hpp -// start catch_analyse.hpp - -// Run and analyse one benchmark - -// start catch_sample_analysis.hpp - -// Benchmark results - -#include -#include -#include -#include - -namespace Catch { -namespace Benchmark { -template struct SampleAnalysis { - std::vector samples; - Estimate mean; - Estimate standard_deviation; - OutlierClassification outliers; - double outlier_variance; - - template operator SampleAnalysis() const - { - std::vector samples2; - samples2.reserve(samples.size()); - std::transform(samples.begin(), samples.end(), - std::back_inserter(samples2), - [](Duration d) { return Duration2(d); }); - return { - std::move(samples2), - mean, - standard_deviation, - outliers, - outlier_variance, - }; - } -}; -} // namespace Benchmark -} // namespace Catch - -// end catch_sample_analysis.hpp -#include -#include -#include - -namespace Catch { -namespace Benchmark { -namespace Detail { -template -SampleAnalysis analyse( - const IConfig &cfg, Environment, Iterator first, Iterator last) -{ - if (!cfg.benchmarkNoAnalysis()) { - std::vector samples; - samples.reserve(last - first); - std::transform(first, last, std::back_inserter(samples), - [](Duration d) { return d.count(); }); - - auto analysis = Catch::Benchmark::Detail::analyse_samples( - cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), - samples.begin(), samples.end()); - auto outliers = Catch::Benchmark::Detail::classify_outliers( - samples.begin(), samples.end()); - - auto wrap_estimate = [](Estimate e) { - return Estimate{ - Duration(e.point), - Duration(e.lower_bound), - Duration(e.upper_bound), - e.confidence_interval, - }; - }; - std::vector samples2; - samples2.reserve(samples.size()); - std::transform(samples.begin(), samples.end(), - std::back_inserter(samples2), [](double d) { return Duration(d); }); - return { - std::move(samples2), - wrap_estimate(analysis.mean), - wrap_estimate(analysis.standard_deviation), - outliers, - analysis.outlier_variance, - }; - } - else { - std::vector samples; - samples.reserve(last - first); - - Duration mean = Duration(0); - int i = 0; - for (auto it = first; it < last; ++it, ++i) { - samples.push_back(Duration(*it)); - mean += Duration(*it); - } - mean /= i; - - return {std::move(samples), Estimate{mean, mean, mean, 0.0}, - Estimate{Duration(0), Duration(0), Duration(0), 0.0}, - OutlierClassification{}, 0.0}; - } -} -} // namespace Detail -} // namespace Benchmark -} // namespace Catch - -// end catch_analyse.hpp -#include -#include -#include -#include -#include - -namespace Catch { -namespace Benchmark { -struct Benchmark { - Benchmark(std::string &&name) - : name(std::move(name)) - { - } - - template - Benchmark(std::string &&name, FUN &&func) - : fun(std::move(func)) - , name(std::move(name)) - { - } - - template - ExecutionPlan> prepare( - const IConfig &cfg, Environment> env) const - { - auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; - auto run_time = std::max(min_time, - std::chrono::duration_cast( - cfg.benchmarkWarmupTime())); - auto &&test = Detail::run_for_at_least( - std::chrono::duration_cast>(run_time), 1, fun); - int new_iters = static_cast( - std::ceil(min_time * test.iterations / test.elapsed)); - return {new_iters, - test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), - fun, - std::chrono::duration_cast>( - cfg.benchmarkWarmupTime()), - Detail::warmup_iterations}; - } - - template void run() - { - IConfigPtr cfg = getCurrentContext().getConfig(); - - auto env = Detail::measure_environment(); - - getResultCapture().benchmarkPreparing(name); - CATCH_TRY - { - auto plan = user_code([&] { return prepare(*cfg, env); }); - - BenchmarkInfo info{name, plan.estimated_duration.count(), - plan.iterations_per_sample, cfg->benchmarkSamples(), - cfg->benchmarkResamples(), env.clock_resolution.mean.count(), - env.clock_cost.mean.count()}; - - getResultCapture().benchmarkStarting(info); - - auto samples = - user_code([&] { return plan.template run(*cfg, env); }); - - auto analysis = - Detail::analyse(*cfg, env, samples.begin(), samples.end()); - BenchmarkStats> stats{info, analysis.samples, - analysis.mean, analysis.standard_deviation, analysis.outliers, - analysis.outlier_variance}; - getResultCapture().benchmarkEnded(stats); - } - CATCH_CATCH_ALL - { - if (translateActiveException() != - Detail::benchmarkErrorMsg) // benchmark errors have been - // reported, otherwise rethrow. - std::rethrow_exception(std::current_exception()); - } - } - - // sets lambda to be used in fun *and* executes benchmark! - template ::value, - int>::type = 0> - Benchmark &operator=(Fun func) - { - fun = Detail::BenchmarkFunction(func); - run(); - return *this; - } - - explicit operator bool() { return true; } - -private: - Detail::BenchmarkFunction fun; - std::string name; -}; -} -} // namespace Catch - -#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1 -#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2 - -#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex) \ - if (Catch::Benchmark::Benchmark BenchmarkName{name}) \ - BenchmarkName = [&](int benchmarkIndex) - -#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name) \ - if (Catch::Benchmark::Benchmark BenchmarkName{name}) \ - BenchmarkName = [&] - -// end catch_benchmark.hpp -// start catch_constructor.hpp - -// Constructor and destructor helpers - -#include - -namespace Catch { -namespace Benchmark { -namespace Detail { -template struct ObjectStorage { - using TStorage = typename std::aligned_storage::value>::type; - - ObjectStorage() - : data() - { - } - - ObjectStorage(const ObjectStorage &other) - { - new (&data) T(other.stored_object()); - } - - ObjectStorage(ObjectStorage &&other) - { - new (&data) T(std::move(other.stored_object())); - } - - ~ObjectStorage() { destruct_on_exit(); } - - template void construct(Args &&...args) - { - new (&data) T(std::forward(args)...); - } - - template - typename std::enable_if::type destruct() - { - stored_object().~T(); - } - -private: - // If this is a constructor benchmark, destruct the underlying object - template - void destruct_on_exit(typename std::enable_if::type * = 0) - { - destruct(); - } - // Otherwise, don't - template - void destruct_on_exit(typename std::enable_if::type * = 0) - { - } - - T &stored_object() { return *static_cast(static_cast(&data)); } - - T const &stored_object() const - { - return *static_cast(static_cast(&data)); - } - - TStorage data; -}; -} - -template using storage_for = Detail::ObjectStorage; - -template -using destructable_object = Detail::ObjectStorage; -} -} - -// end catch_constructor.hpp -// end catch_benchmarking_all.hpp -#endif - -#endif // ! CATCH_CONFIG_IMPL_ONLY - -#ifdef CATCH_IMPL -// start catch_impl.hpp - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -// Keep these here for external reporters -// start catch_test_case_tracker.h - -#include -#include -#include - -namespace Catch { -namespace TestCaseTracking { - -struct NameAndLocation { - std::string name; - SourceLineInfo location; - - NameAndLocation(std::string const &_name, SourceLineInfo const &_location); - friend bool operator==( - NameAndLocation const &lhs, NameAndLocation const &rhs) - { - return lhs.name == rhs.name && lhs.location == rhs.location; - } -}; - -class ITracker; - -using ITrackerPtr = std::shared_ptr; - -class ITracker { - NameAndLocation m_nameAndLocation; - -public: - ITracker(NameAndLocation const &nameAndLoc) - : m_nameAndLocation(nameAndLoc) - { - } - - // static queries - NameAndLocation const &nameAndLocation() const { return m_nameAndLocation; } - - virtual ~ITracker(); - - // dynamic queries - virtual bool isComplete() const = 0; // Successfully completed or failed - virtual bool isSuccessfullyCompleted() const = 0; - virtual bool isOpen() const = 0; // Started but not complete - virtual bool hasChildren() const = 0; - virtual bool hasStarted() const = 0; - - virtual ITracker &parent() = 0; - - // actions - virtual void close() = 0; // Successfully complete - virtual void fail() = 0; - virtual void markAsNeedingAnotherRun() = 0; - - virtual void addChild(ITrackerPtr const &child) = 0; - virtual ITrackerPtr findChild(NameAndLocation const &nameAndLocation) = 0; - virtual void openChild() = 0; - - // Debug/ checking - virtual bool isSectionTracker() const = 0; - virtual bool isGeneratorTracker() const = 0; -}; - -class TrackerContext { - - enum RunState { NotStarted, Executing, CompletedCycle }; - - ITrackerPtr m_rootTracker; - ITracker *m_currentTracker = nullptr; - RunState m_runState = NotStarted; - -public: - ITracker &startRun(); - void endRun(); - - void startCycle(); - void completeCycle(); - - bool completedCycle() const; - ITracker ¤tTracker(); - void setCurrentTracker(ITracker *tracker); -}; - -class TrackerBase : public ITracker { -protected: - enum CycleState { - NotStarted, - Executing, - ExecutingChildren, - NeedsAnotherRun, - CompletedSuccessfully, - Failed - }; - - using Children = std::vector; - TrackerContext &m_ctx; - ITracker *m_parent; - Children m_children; - CycleState m_runState = NotStarted; - -public: - TrackerBase(NameAndLocation const &nameAndLocation, TrackerContext &ctx, - ITracker *parent); - - bool isComplete() const override; - bool isSuccessfullyCompleted() const override; - bool isOpen() const override; - bool hasChildren() const override; - bool hasStarted() const override { return m_runState != NotStarted; } - - void addChild(ITrackerPtr const &child) override; - - ITrackerPtr findChild(NameAndLocation const &nameAndLocation) override; - ITracker &parent() override; - - void openChild() override; - - bool isSectionTracker() const override; - bool isGeneratorTracker() const override; - - void open(); - - void close() override; - void fail() override; - void markAsNeedingAnotherRun() override; - -private: - void moveToParent(); - void moveToThis(); -}; - -class SectionTracker : public TrackerBase { - std::vector m_filters; - std::string m_trimmed_name; - -public: - SectionTracker(NameAndLocation const &nameAndLocation, TrackerContext &ctx, - ITracker *parent); - - bool isSectionTracker() const override; - - bool isComplete() const override; - - static SectionTracker &acquire( - TrackerContext &ctx, NameAndLocation const &nameAndLocation); - - void tryOpen(); - - void addInitialFilters(std::vector const &filters); - void addNextFilters(std::vector const &filters); - //! Returns filters active in this tracker - std::vector const &getFilters() const; - //! Returns whitespace-trimmed name of the tracked section - std::string const &trimmedName() const; -}; - -} // namespace TestCaseTracking - -using TestCaseTracking::ITracker; -using TestCaseTracking::SectionTracker; -using TestCaseTracking::TrackerContext; - -} // namespace Catch - -// end catch_test_case_tracker.h - -// start catch_leak_detector.h - -namespace Catch { - -struct LeakDetector { - LeakDetector(); - ~LeakDetector(); -}; - -} -// end catch_leak_detector.h -// Cpp files will be included in the single-header file here -// start catch_stats.cpp - -// Statistical analysis tools - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) - -#include -#include - -#if defined(CATCH_CONFIG_USE_ASYNC) -#include -#endif - -namespace { -double erf_inv(double x) -{ - // Code accompanying the article "Approximating the erfinv function" in GPU - // Computing Gems, Volume 2 - double w, p; - - w = -log((1.0 - x) * (1.0 + x)); - - if (w < 6.250000) { - w = w - 3.125000; - p = -3.6444120640178196996e-21; - p = -1.685059138182016589e-19 + p * w; - p = 1.2858480715256400167e-18 + p * w; - p = 1.115787767802518096e-17 + p * w; - p = -1.333171662854620906e-16 + p * w; - p = 2.0972767875968561637e-17 + p * w; - p = 6.6376381343583238325e-15 + p * w; - p = -4.0545662729752068639e-14 + p * w; - p = -8.1519341976054721522e-14 + p * w; - p = 2.6335093153082322977e-12 + p * w; - p = -1.2975133253453532498e-11 + p * w; - p = -5.4154120542946279317e-11 + p * w; - p = 1.051212273321532285e-09 + p * w; - p = -4.1126339803469836976e-09 + p * w; - p = -2.9070369957882005086e-08 + p * w; - p = 4.2347877827932403518e-07 + p * w; - p = -1.3654692000834678645e-06 + p * w; - p = -1.3882523362786468719e-05 + p * w; - p = 0.0001867342080340571352 + p * w; - p = -0.00074070253416626697512 + p * w; - p = -0.0060336708714301490533 + p * w; - p = 0.24015818242558961693 + p * w; - p = 1.6536545626831027356 + p * w; - } - else if (w < 16.000000) { - w = sqrt(w) - 3.250000; - p = 2.2137376921775787049e-09; - p = 9.0756561938885390979e-08 + p * w; - p = -2.7517406297064545428e-07 + p * w; - p = 1.8239629214389227755e-08 + p * w; - p = 1.5027403968909827627e-06 + p * w; - p = -4.013867526981545969e-06 + p * w; - p = 2.9234449089955446044e-06 + p * w; - p = 1.2475304481671778723e-05 + p * w; - p = -4.7318229009055733981e-05 + p * w; - p = 6.8284851459573175448e-05 + p * w; - p = 2.4031110387097893999e-05 + p * w; - p = -0.0003550375203628474796 + p * w; - p = 0.00095328937973738049703 + p * w; - p = -0.0016882755560235047313 + p * w; - p = 0.0024914420961078508066 + p * w; - p = -0.0037512085075692412107 + p * w; - p = 0.005370914553590063617 + p * w; - p = 1.0052589676941592334 + p * w; - p = 3.0838856104922207635 + p * w; - } - else { - w = sqrt(w) - 5.000000; - p = -2.7109920616438573243e-11; - p = -2.5556418169965252055e-10 + p * w; - p = 1.5076572693500548083e-09 + p * w; - p = -3.7894654401267369937e-09 + p * w; - p = 7.6157012080783393804e-09 + p * w; - p = -1.4960026627149240478e-08 + p * w; - p = 2.9147953450901080826e-08 + p * w; - p = -6.7711997758452339498e-08 + p * w; - p = 2.2900482228026654717e-07 + p * w; - p = -9.9298272942317002539e-07 + p * w; - p = 4.5260625972231537039e-06 + p * w; - p = -1.9681778105531670567e-05 + p * w; - p = 7.5995277030017761139e-05 + p * w; - p = -0.00021503011930044477347 + p * w; - p = -0.00013871931833623122026 + p * w; - p = 1.0103004648645343977 + p * w; - p = 4.8499064014085844221 + p * w; - } - return p * x; -} - -double standard_deviation( - std::vector::iterator first, std::vector::iterator last) -{ - auto m = Catch::Benchmark::Detail::mean(first, last); - double variance = std::accumulate(first, last, 0., [m](double a, double b) { - double diff = b - m; - return a + diff * diff; - }) / (last - first); - return std::sqrt(variance); -} - -} - -namespace Catch { -namespace Benchmark { -namespace Detail { - -double weighted_average_quantile(int k, int q, - std::vector::iterator first, std::vector::iterator last) -{ - auto count = last - first; - double idx = (count - 1) * k / static_cast(q); - int j = static_cast(idx); - double g = idx - j; - std::nth_element(first, first + j, last); - auto xj = first[j]; - if (g == 0) - return xj; - - auto xj1 = *std::min_element(first + (j + 1), last); - return xj + g * (xj1 - xj); -} - -double erfc_inv(double x) { return erf_inv(1.0 - x); } - -double normal_quantile(double p) -{ - static const double ROOT_TWO = std::sqrt(2.0); - - double result = 0.0; - assert(p >= 0 && p <= 1); - if (p < 0 || p > 1) { - return result; - } - - result = -erfc_inv(2.0 * p); - // result *= normal distribution standard deviation (1.0) * sqrt(2) - result *= /*sd * */ ROOT_TWO; - // result += normal disttribution mean (0) - return result; -} - -double outlier_variance(Estimate mean, Estimate stddev, int n) -{ - double sb = stddev.point; - double mn = mean.point / n; - double mg_min = mn / 2.; - double sg = (std::min)(mg_min / 4., sb / std::sqrt(n)); - double sg2 = sg * sg; - double sb2 = sb * sb; - - auto c_max = [n, mn, sb2, sg2](double x) -> double { - double k = mn - x; - double d = k * k; - double nd = n * d; - double k0 = -n * nd; - double k1 = sb2 - n * sg2 + nd; - double det = k1 * k1 - 4 * sg2 * k0; - return (int)(-2. * k0 / (k1 + std::sqrt(det))); - }; - - auto var_out = [n, sb2, sg2](double c) { - double nc = n - c; - return (nc / n) * (sb2 - nc * sg2); - }; - - return (std::min)( - var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / - sb2; -} - -bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, - std::vector::iterator first, std::vector::iterator last) -{ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS - static std::random_device entropy; - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - - auto n = static_cast(last - - first); // seriously, one can't use integral types without hell in C++ - - auto mean = &Detail::mean::iterator>; - auto stddev = &standard_deviation; - -#if defined(CATCH_CONFIG_USE_ASYNC) - auto Estimate = [=](double (*f)(std::vector::iterator, - std::vector::iterator)) { - auto seed = entropy(); - return std::async(std::launch::async, [=] { - std::mt19937 rng(seed); - auto resampled = resample(rng, n_resamples, first, last, f); - return bootstrap(confidence_level, first, last, resampled, f); - }); - }; - - auto mean_future = Estimate(mean); - auto stddev_future = Estimate(stddev); - - auto mean_estimate = mean_future.get(); - auto stddev_estimate = stddev_future.get(); -#else - auto Estimate = [=](double (*f)(std::vector::iterator, - std::vector::iterator)) { - auto seed = entropy(); - std::mt19937 rng(seed); - auto resampled = resample(rng, n_resamples, first, last, f); - return bootstrap(confidence_level, first, last, resampled, f); - }; - - auto mean_estimate = Estimate(mean); - auto stddev_estimate = Estimate(stddev); -#endif // CATCH_USE_ASYNC - - double outlier_variance = - Detail::outlier_variance(mean_estimate, stddev_estimate, n); - - return {mean_estimate, stddev_estimate, outlier_variance}; -} -} // namespace Detail -} // namespace Benchmark -} // namespace Catch - -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING -// end catch_stats.cpp -// start catch_approx.cpp - -#include -#include - -namespace { - -// Performs equivalent check of std::fabs(lhs - rhs) <= margin -// But without the subtraction to allow for INFINITY in comparison -bool marginComparison(double lhs, double rhs, double margin) -{ - return (lhs + margin >= rhs) && (rhs + margin >= lhs); -} - -} - -namespace Catch { -namespace Detail { - -Approx::Approx(double value) - : m_epsilon(std::numeric_limits::epsilon() * 100) - , m_margin(0.0) - , m_scale(0.0) - , m_value(value) -{ -} - -Approx Approx::custom() { return Approx(0); } - -Approx Approx::operator-() const -{ - auto temp(*this); - temp.m_value = -temp.m_value; - return temp; -} - -std::string Approx::toString() const -{ - ReusableStringStream rss; - rss << "Approx( " << ::Catch::Detail::stringify(m_value) << " )"; - return rss.str(); -} - -bool Approx::equalityComparisonImpl(const double other) const -{ - // First try with fixed margin, then compute margin based on epsilon, scale - // and Approx's value Thanks to Richard Harris for his help refining the - // scaled margin value - return marginComparison(m_value, other, m_margin) || - marginComparison(m_value, other, - m_epsilon * - (m_scale + std::fabs(std::isinf(m_value) ? 0 : m_value))); -} - -void Approx::setMargin(double newMargin) -{ - CATCH_ENFORCE(newMargin >= 0, - "Invalid Approx::margin: " - << newMargin << '.' << " Approx::Margin has to be non-negative."); - m_margin = newMargin; -} - -void Approx::setEpsilon(double newEpsilon) -{ - CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0, - "Invalid Approx::epsilon: " << newEpsilon << '.' - << " Approx::epsilon has to be in [0, 1]"); - m_epsilon = newEpsilon; -} - -} // end namespace Detail - -namespace literals { -Detail::Approx operator"" _a(long double val) { return Detail::Approx(val); } -Detail::Approx operator"" _a(unsigned long long val) -{ - return Detail::Approx(val); -} -} // end namespace literals - -std::string StringMaker::convert( - Catch::Detail::Approx const &value) -{ - return value.toString(); -} - -} // end namespace Catch -// end catch_approx.cpp -// start catch_assertionhandler.cpp - -// start catch_debugger.h - -namespace Catch { -bool isDebuggerActive(); -} - -#ifdef CATCH_PLATFORM_MAC - -#if defined(__i386__) || defined(__x86_64__) -#define CATCH_TRAP() __asm__("int $3\n" : :) /* NOLINT */ -#elif defined(__aarch64__) -#define CATCH_TRAP() __asm__(".inst 0xd4200000") -#endif - -#elif defined(CATCH_PLATFORM_IPHONE) - -// use inline assembler -#if defined(__i386__) || defined(__x86_64__) -#define CATCH_TRAP() __asm__("int $3") -#elif defined(__aarch64__) -#define CATCH_TRAP() __asm__(".inst 0xd4200000") -#elif defined(__arm__) && !defined(__thumb__) -#define CATCH_TRAP() __asm__(".inst 0xe7f001f0") -#elif defined(__arm__) && defined(__thumb__) -#define CATCH_TRAP() __asm__(".inst 0xde01") -#endif - -#elif defined(CATCH_PLATFORM_LINUX) -// If we can use inline assembler, do it because this allows us to break -// directly at the location of the failing check instead of breaking inside -// raise() called from it, i.e. one stack frame below. -#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) -#define CATCH_TRAP() asm volatile("int $3") /* NOLINT */ -#else // Fall back to the generic way. -#include - -#define CATCH_TRAP() raise(SIGTRAP) -#endif -#elif defined(_MSC_VER) -#define CATCH_TRAP() __debugbreak() -#elif defined(__MINGW32__) -extern "C" __declspec(dllimport) void __stdcall DebugBreak(); -#define CATCH_TRAP() DebugBreak() -#endif - -#ifndef CATCH_BREAK_INTO_DEBUGGER -#ifdef CATCH_TRAP -#define CATCH_BREAK_INTO_DEBUGGER() \ - [] { \ - if (Catch::isDebuggerActive()) { \ - CATCH_TRAP(); \ - } \ - }() -#else -#define CATCH_BREAK_INTO_DEBUGGER() [] {}() -#endif -#endif - -// end catch_debugger.h -// start catch_run_context.h - -// start catch_fatal_condition.h - -#include - -namespace Catch { - -// Wrapper for platform-specific fatal error (signals/SEH) handlers -// -// Tries to be cooperative with other handlers, and not step over -// other handlers. This means that unknown structured exceptions -// are passed on, previous signal handlers are called, and so on. -// -// Can only be instantiated once, and assumes that once a signal -// is caught, the binary will end up terminating. Thus, there -class FatalConditionHandler { - bool m_started = false; - - // Install/disengage implementation for specific platform. - // Should be if-defed to work on current platform, can assume - // engage-disengage 1:1 pairing. - void engage_platform(); - void disengage_platform(); - -public: - // Should also have platform-specific implementations as needed - FatalConditionHandler(); - ~FatalConditionHandler(); - - void engage() - { - assert(!m_started && "Handler cannot be installed twice."); - m_started = true; - engage_platform(); - } - - void disengage() - { - assert(m_started && - "Handler cannot be uninstalled without being installed first"); - m_started = false; - disengage_platform(); - } -}; - -//! Simple RAII guard for (dis)engaging the FatalConditionHandler -class FatalConditionHandlerGuard { - FatalConditionHandler *m_handler; - -public: - FatalConditionHandlerGuard(FatalConditionHandler *handler) - : m_handler(handler) - { - m_handler->engage(); - } - ~FatalConditionHandlerGuard() { m_handler->disengage(); } -}; - -} // end namespace Catch - -// end catch_fatal_condition.h -#include - -namespace Catch { - -struct IMutableContext; - -/////////////////////////////////////////////////////////////////////////// - -class RunContext : public IResultCapture, public IRunner { - -public: - RunContext(RunContext const &) = delete; - RunContext &operator=(RunContext const &) = delete; - - explicit RunContext( - IConfigPtr const &_config, IStreamingReporterPtr &&reporter); - - ~RunContext() override; - - void testGroupStarting(std::string const &testSpec, std::size_t groupIndex, - std::size_t groupsCount); - void testGroupEnded(std::string const &testSpec, Totals const &totals, - std::size_t groupIndex, std::size_t groupsCount); - - Totals runTest(TestCase const &testCase); - - IConfigPtr config() const; - IStreamingReporter &reporter() const; - -public: // IResultCapture - // Assertion handlers - void handleExpr(AssertionInfo const &info, ITransientExpression const &expr, - AssertionReaction &reaction) override; - void handleMessage(AssertionInfo const &info, ResultWas::OfType resultType, - StringRef const &message, AssertionReaction &reaction) override; - void handleUnexpectedExceptionNotThrown( - AssertionInfo const &info, AssertionReaction &reaction) override; - void handleUnexpectedInflightException(AssertionInfo const &info, - std::string const &message, AssertionReaction &reaction) override; - void handleIncomplete(AssertionInfo const &info) override; - void handleNonExpr(AssertionInfo const &info, ResultWas::OfType resultType, - AssertionReaction &reaction) override; - - bool sectionStarted( - SectionInfo const §ionInfo, Counts &assertions) override; - - void sectionEnded(SectionEndInfo const &endInfo) override; - void sectionEndedEarly(SectionEndInfo const &endInfo) override; - - auto acquireGeneratorTracker(StringRef generatorName, - SourceLineInfo const &lineInfo) -> IGeneratorTracker & override; - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) - void benchmarkPreparing(std::string const &name) override; - void benchmarkStarting(BenchmarkInfo const &info) override; - void benchmarkEnded(BenchmarkStats<> const &stats) override; - void benchmarkFailed(std::string const &error) override; -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - - void pushScopedMessage(MessageInfo const &message) override; - void popScopedMessage(MessageInfo const &message) override; - - void emplaceUnscopedMessage(MessageBuilder const &builder) override; - - std::string getCurrentTestName() const override; - - const AssertionResult *getLastResult() const override; - - void exceptionEarlyReported() override; - - void handleFatalErrorCondition(StringRef message) override; - - bool lastAssertionPassed() override; - - void assertionPassed() override; - -public: - // !TBD We need to do this another way! - bool aborting() const final; - -private: - void runCurrentTest( - std::string &redirectedCout, std::string &redirectedCerr); - void invokeActiveTestCase(); - - void resetAssertionInfo(); - bool testForMissingAssertions(Counts &assertions); - - void assertionEnded(AssertionResult const &result); - void reportExpr(AssertionInfo const &info, ResultWas::OfType resultType, - ITransientExpression const *expr, bool negated); - - void populateReaction(AssertionReaction &reaction); - -private: - void handleUnfinishedSections(); - - TestRunInfo m_runInfo; - IMutableContext &m_context; - TestCase const *m_activeTestCase = nullptr; - ITracker *m_testCaseTracker = nullptr; - Option m_lastResult; - - IConfigPtr m_config; - Totals m_totals; - IStreamingReporterPtr m_reporter; - std::vector m_messages; - std::vector - m_messageScopes; /* Keeps owners of so-called unscoped messages. */ - AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; - std::vector m_activeSections; - TrackerContext m_trackerContext; - FatalConditionHandler m_fatalConditionhandler; - bool m_lastAssertionPassed = false; - bool m_shouldReportUnexpected = true; - bool m_includeSuccessfulResults; -}; - -void seedRng(IConfig const &config); -unsigned int rngSeed(); -} // end namespace Catch - -// end catch_run_context.h -namespace Catch { - -namespace { -auto operator<<(std::ostream &os, ITransientExpression const &expr) - -> std::ostream & -{ - expr.streamReconstructedExpression(os); - return os; -} -} - -LazyExpression::LazyExpression(bool isNegated) - : m_isNegated(isNegated) -{ -} - -LazyExpression::LazyExpression(LazyExpression const &other) - : m_isNegated(other.m_isNegated) -{ -} - -LazyExpression::operator bool() const -{ - return m_transientExpression != nullptr; -} - -auto operator<<(std::ostream &os, LazyExpression const &lazyExpr) - -> std::ostream & -{ - if (lazyExpr.m_isNegated) - os << "!"; - - if (lazyExpr) { - if (lazyExpr.m_isNegated && - lazyExpr.m_transientExpression->isBinaryExpression()) - os << "(" << *lazyExpr.m_transientExpression << ")"; - else - os << *lazyExpr.m_transientExpression; - } - else { - os << "{** error - unchecked empty expression requested **}"; - } - return os; -} - -AssertionHandler::AssertionHandler(StringRef const ¯oName, - SourceLineInfo const &lineInfo, StringRef capturedExpression, - ResultDisposition::Flags resultDisposition) - : m_assertionInfo{macroName, lineInfo, capturedExpression, - resultDisposition} - , m_resultCapture(getResultCapture()) -{ -} - -void AssertionHandler::handleExpr(ITransientExpression const &expr) -{ - m_resultCapture.handleExpr(m_assertionInfo, expr, m_reaction); -} -void AssertionHandler::handleMessage( - ResultWas::OfType resultType, StringRef const &message) -{ - m_resultCapture.handleMessage( - m_assertionInfo, resultType, message, m_reaction); -} - -auto AssertionHandler::allowThrows() const -> bool -{ - return getCurrentContext().getConfig()->allowThrows(); -} - -void AssertionHandler::complete() -{ - setCompleted(); - if (m_reaction.shouldDebugBreak) { - - // If you find your debugger stopping you here then go one level up on - // the call-stack for the code that caused it (typically a failed - // assertion) - - // (To go back to the test and change execution, jump over the throw, - // next) - CATCH_BREAK_INTO_DEBUGGER(); - } - if (m_reaction.shouldThrow) { -#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - throw Catch::TestFailureException(); -#else - CATCH_ERROR("Test failure requires aborting test!"); -#endif - } -} -void AssertionHandler::setCompleted() { m_completed = true; } - -void AssertionHandler::handleUnexpectedInflightException() -{ - m_resultCapture.handleUnexpectedInflightException( - m_assertionInfo, Catch::translateActiveException(), m_reaction); -} - -void AssertionHandler::handleExceptionThrownAsExpected() -{ - m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); -} -void AssertionHandler::handleExceptionNotThrownAsExpected() -{ - m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); -} - -void AssertionHandler::handleUnexpectedExceptionNotThrown() -{ - m_resultCapture.handleUnexpectedExceptionNotThrown( - m_assertionInfo, m_reaction); -} - -void AssertionHandler::handleThrowingCallSkipped() -{ - m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); -} - -// This is the overload that takes a string and infers the Equals matcher from -// it The more general overload, that takes any string matcher, is in -// catch_capture_matchers.cpp -void handleExceptionMatchExpr(AssertionHandler &handler, std::string const &str, - StringRef const &matcherString) -{ - handleExceptionMatchExpr(handler, Matchers::Equals(str), matcherString); -} - -} // namespace Catch -// end catch_assertionhandler.cpp -// start catch_assertionresult.cpp - -namespace Catch { -AssertionResultData::AssertionResultData( - ResultWas::OfType _resultType, LazyExpression const &_lazyExpression) - : lazyExpression(_lazyExpression) - , resultType(_resultType) -{ -} - -std::string AssertionResultData::reconstructExpression() const -{ - - if (reconstructedExpression.empty()) { - if (lazyExpression) { - ReusableStringStream rss; - rss << lazyExpression; - reconstructedExpression = rss.str(); - } - } - return reconstructedExpression; -} - -AssertionResult::AssertionResult( - AssertionInfo const &info, AssertionResultData const &data) - : m_info(info) - , m_resultData(data) -{ -} - -// Result was a success -bool AssertionResult::succeeded() const -{ - return Catch::isOk(m_resultData.resultType); -} - -// Result was a success, or failure is suppressed -bool AssertionResult::isOk() const -{ - return Catch::isOk(m_resultData.resultType) || - shouldSuppressFailure(m_info.resultDisposition); -} - -ResultWas::OfType AssertionResult::getResultType() const -{ - return m_resultData.resultType; -} - -bool AssertionResult::hasExpression() const -{ - return !m_info.capturedExpression.empty(); -} - -bool AssertionResult::hasMessage() const -{ - return !m_resultData.message.empty(); -} - -std::string AssertionResult::getExpression() const -{ - // Possibly overallocating by 3 characters should be basically free - std::string expr; - expr.reserve(m_info.capturedExpression.size() + 3); - if (isFalseTest(m_info.resultDisposition)) { - expr += "!("; - } - expr += m_info.capturedExpression; - if (isFalseTest(m_info.resultDisposition)) { - expr += ')'; - } - return expr; -} - -std::string AssertionResult::getExpressionInMacro() const -{ - std::string expr; - if (m_info.macroName.empty()) - expr = static_cast(m_info.capturedExpression); - else { - expr.reserve( - m_info.macroName.size() + m_info.capturedExpression.size() + 4); - expr += m_info.macroName; - expr += "( "; - expr += m_info.capturedExpression; - expr += " )"; - } - return expr; -} - -bool AssertionResult::hasExpandedExpression() const -{ - return hasExpression() && getExpandedExpression() != getExpression(); -} - -std::string AssertionResult::getExpandedExpression() const -{ - std::string expr = m_resultData.reconstructExpression(); - return expr.empty() ? getExpression() : expr; -} - -std::string AssertionResult::getMessage() const { return m_resultData.message; } -SourceLineInfo AssertionResult::getSourceInfo() const -{ - return m_info.lineInfo; -} - -StringRef AssertionResult::getTestMacroName() const { return m_info.macroName; } - -} // end namespace Catch -// end catch_assertionresult.cpp -// start catch_capture_matchers.cpp - -namespace Catch { - -using StringMatcher = Matchers::Impl::MatcherBase; - -// This is the general overload that takes a any string matcher -// There is another overload, in catch_assertionhandler.h/.cpp, that only takes -// a string and infers the Equals matcher (so the header does not mention -// matchers) -void handleExceptionMatchExpr(AssertionHandler &handler, - StringMatcher const &matcher, StringRef const &matcherString) -{ - std::string exceptionMessage = Catch::translateActiveException(); - MatchExpr expr( - exceptionMessage, matcher, matcherString); - handler.handleExpr(expr); -} - -} // namespace Catch -// end catch_capture_matchers.cpp -// start catch_commandline.cpp - -// start catch_commandline.h - -// start catch_clara.h - -// Use Catch's value for console width (store Clara's off to the side, if -// present) -#ifdef CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH \ - CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#endif -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - 1 - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#pragma clang diagnostic ignored "-Wexit-time-destructors" -#pragma clang diagnostic ignored "-Wshadow" -#endif - -// start clara.hpp -// Copyright 2017 Two Blue Cubes Ltd. All rights reserved. -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See https://github.com/philsquared/Clara for more details - -// Clara v1.1.5 - -#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 -#endif - -#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH \ - CATCH_CLARA_CONFIG_CONSOLE_WIDTH -#endif - -#ifndef CLARA_CONFIG_OPTIONAL_TYPE -#ifdef __has_include -#if __has_include() && __cplusplus >= 201703L -#include -#define CLARA_CONFIG_OPTIONAL_TYPE std::optional -#endif -#endif -#endif - -// ----------- #included from clara_textflow.hpp ----------- - -// TextFlowCpp -// -// A single-header library for wrapping and laying out basic text, by Phil Nash -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// This project is hosted at https://github.com/philsquared/textflowcpp - -#include -#include -#include -#include - -#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 -#endif - -namespace Catch { -namespace clara { -namespace TextFlow { - -inline auto isWhitespace(char c) -> bool -{ - static std::string chars = " \t\n\r"; - return chars.find(c) != std::string::npos; -} -inline auto isBreakableBefore(char c) -> bool -{ - static std::string chars = "[({<|"; - return chars.find(c) != std::string::npos; -} -inline auto isBreakableAfter(char c) -> bool -{ - static std::string chars = "])}>.,:;*+-=&/\\"; - return chars.find(c) != std::string::npos; -} - -class Columns; - -class Column { - std::vector m_strings; - size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; - size_t m_indent = 0; - size_t m_initialIndent = std::string::npos; - -public: - class iterator { - friend Column; - - Column const &m_column; - size_t m_stringIndex = 0; - size_t m_pos = 0; - - size_t m_len = 0; - size_t m_end = 0; - bool m_suffix = false; - - iterator(Column const &column, size_t stringIndex) - : m_column(column) - , m_stringIndex(stringIndex) - { - } - - auto line() const -> std::string const & - { - return m_column.m_strings[m_stringIndex]; - } - - auto isBoundary(size_t at) const -> bool - { - assert(at > 0); - assert(at <= line().size()); - - return at == line().size() || - (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) || - isBreakableBefore(line()[at]) || - isBreakableAfter(line()[at - 1]); - } - - void calcLength() - { - assert(m_stringIndex < m_column.m_strings.size()); - - m_suffix = false; - auto width = m_column.m_width - indent(); - m_end = m_pos; - if (line()[m_pos] == '\n') { - ++m_end; - } - while (m_end < line().size() && line()[m_end] != '\n') - ++m_end; - - if (m_end < m_pos + width) { - m_len = m_end - m_pos; - } - else { - size_t len = width; - while (len > 0 && !isBoundary(m_pos + len)) - --len; - while (len > 0 && isWhitespace(line()[m_pos + len - 1])) - --len; - - if (len > 0) { - m_len = len; - } - else { - m_suffix = true; - m_len = width - 1; - } - } - } - - auto indent() const -> size_t - { - auto initial = m_pos == 0 && m_stringIndex == 0 - ? m_column.m_initialIndent - : std::string::npos; - return initial == std::string::npos ? m_column.m_indent : initial; - } - - auto addIndentAndSuffix(std::string const &plain) const -> std::string - { - return std::string(indent(), ' ') + - (m_suffix ? plain + "-" : plain); - } - - public: - using difference_type = std::ptrdiff_t; - using value_type = std::string; - using pointer = value_type *; - using reference = value_type &; - using iterator_category = std::forward_iterator_tag; - - explicit iterator(Column const &column) - : m_column(column) - { - assert(m_column.m_width > m_column.m_indent); - assert(m_column.m_initialIndent == std::string::npos || - m_column.m_width > m_column.m_initialIndent); - calcLength(); - if (m_len == 0) - m_stringIndex++; // Empty string - } - - auto operator*() const -> std::string - { - assert(m_stringIndex < m_column.m_strings.size()); - assert(m_pos <= m_end); - return addIndentAndSuffix(line().substr(m_pos, m_len)); - } - - auto operator++() -> iterator & - { - m_pos += m_len; - if (m_pos < line().size() && line()[m_pos] == '\n') - m_pos += 1; - else - while (m_pos < line().size() && isWhitespace(line()[m_pos])) - ++m_pos; - - if (m_pos == line().size()) { - m_pos = 0; - ++m_stringIndex; - } - if (m_stringIndex < m_column.m_strings.size()) - calcLength(); - return *this; - } - auto operator++(int) -> iterator - { - iterator prev(*this); - operator++(); - return prev; - } - - auto operator==(iterator const &other) const -> bool - { - return m_pos == other.m_pos && - m_stringIndex == other.m_stringIndex && - &m_column == &other.m_column; - } - auto operator!=(iterator const &other) const -> bool - { - return !operator==(other); - } - }; - using const_iterator = iterator; - - explicit Column(std::string const &text) { m_strings.push_back(text); } - - auto width(size_t newWidth) -> Column & - { - assert(newWidth > 0); - m_width = newWidth; - return *this; - } - auto indent(size_t newIndent) -> Column & - { - m_indent = newIndent; - return *this; - } - auto initialIndent(size_t newIndent) -> Column & - { - m_initialIndent = newIndent; - return *this; - } - - auto width() const -> size_t { return m_width; } - auto begin() const -> iterator { return iterator(*this); } - auto end() const -> iterator { return {*this, m_strings.size()}; } - - inline friend std::ostream &operator<<(std::ostream &os, Column const &col) - { - bool first = true; - for (auto line : col) { - if (first) - first = false; - else - os << "\n"; - os << line; - } - return os; - } - - auto operator+(Column const &other) -> Columns; - - auto toString() const -> std::string - { - std::ostringstream oss; - oss << *this; - return oss.str(); - } -}; - -class Spacer : public Column { - -public: - explicit Spacer(size_t spaceWidth) - : Column("") - { - width(spaceWidth); - } -}; - -class Columns { - std::vector m_columns; - -public: - class iterator { - friend Columns; - struct EndTag { }; - - std::vector const &m_columns; - std::vector m_iterators; - size_t m_activeIterators; - - iterator(Columns const &columns, EndTag) - : m_columns(columns.m_columns) - , m_activeIterators(0) - { - m_iterators.reserve(m_columns.size()); - - for (auto const &col : m_columns) - m_iterators.push_back(col.end()); - } - - public: - using difference_type = std::ptrdiff_t; - using value_type = std::string; - using pointer = value_type *; - using reference = value_type &; - using iterator_category = std::forward_iterator_tag; - - explicit iterator(Columns const &columns) - : m_columns(columns.m_columns) - , m_activeIterators(m_columns.size()) - { - m_iterators.reserve(m_columns.size()); - - for (auto const &col : m_columns) - m_iterators.push_back(col.begin()); - } - - auto operator==(iterator const &other) const -> bool - { - return m_iterators == other.m_iterators; - } - auto operator!=(iterator const &other) const -> bool - { - return m_iterators != other.m_iterators; - } - auto operator*() const -> std::string - { - std::string row, padding; - - for (size_t i = 0; i < m_columns.size(); ++i) { - auto width = m_columns[i].width(); - if (m_iterators[i] != m_columns[i].end()) { - std::string col = *m_iterators[i]; - row += padding + col; - if (col.size() < width) - padding = std::string(width - col.size(), ' '); - else - padding = ""; - } - else { - padding += std::string(width, ' '); - } - } - return row; - } - auto operator++() -> iterator & - { - for (size_t i = 0; i < m_columns.size(); ++i) { - if (m_iterators[i] != m_columns[i].end()) - ++m_iterators[i]; - } - return *this; - } - auto operator++(int) -> iterator - { - iterator prev(*this); - operator++(); - return prev; - } - }; - using const_iterator = iterator; - - auto begin() const -> iterator { return iterator(*this); } - auto end() const -> iterator { return {*this, iterator::EndTag()}; } - - auto operator+=(Column const &col) -> Columns & - { - m_columns.push_back(col); - return *this; - } - auto operator+(Column const &col) -> Columns - { - Columns combined = *this; - combined += col; - return combined; - } - - inline friend std::ostream &operator<<( - std::ostream &os, Columns const &cols) - { - - bool first = true; - for (auto line : cols) { - if (first) - first = false; - else - os << "\n"; - os << line; - } - return os; - } - - auto toString() const -> std::string - { - std::ostringstream oss; - oss << *this; - return oss.str(); - } -}; - -inline auto Column::operator+(Column const &other) -> Columns -{ - Columns cols; - cols += *this; - cols += other; - return cols; -} -} - -} -} - -// ----------- end of #include from clara_textflow.hpp ----------- -// ........... back in clara.hpp - -#include -#include -#include -#include -#include - -#if !defined(CATCH_PLATFORM_WINDOWS) && \ - (defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || \ - defined(_MSC_VER)) -#define CATCH_PLATFORM_WINDOWS -#endif - -namespace Catch { -namespace clara { -namespace detail { - -// Traits for extracting arg and return type of lambdas (for single argument -// lambdas) -template -struct UnaryLambdaTraits : UnaryLambdaTraits { }; - -template -struct UnaryLambdaTraits { - static const bool isValid = false; -}; - -template -struct UnaryLambdaTraits { - static const bool isValid = true; - using ArgType = typename std::remove_const< - typename std::remove_reference::type>::type; - using ReturnType = ReturnT; -}; - -class TokenStream; - -// Transport for raw args (copied from main args, or supplied via init list for -// testing) -class Args { - friend TokenStream; - std::string m_exeName; - std::vector m_args; - -public: - Args(int argc, char const *const *argv) - : m_exeName(argv[0]) - , m_args(argv + 1, argv + argc) - { - } - - Args(std::initializer_list args) - : m_exeName(*args.begin()) - , m_args(args.begin() + 1, args.end()) - { - } - - auto exeName() const -> std::string { return m_exeName; } -}; - -// Wraps a token coming from a token stream. These may not directly correspond -// to strings as a single string may encode an option + its argument if the : or -// = form is used -enum class TokenType { Option, Argument }; -struct Token { - TokenType type; - std::string token; -}; - -inline auto isOptPrefix(char c) -> bool -{ - return c == '-' -#ifdef CATCH_PLATFORM_WINDOWS - || c == '/' -#endif - ; -} - -// Abstracts iterators into args as a stream of tokens, with option arguments -// uniformly handled -class TokenStream { - using Iterator = std::vector::const_iterator; - Iterator it; - Iterator itEnd; - std::vector m_tokenBuffer; - - void loadBuffer() - { - m_tokenBuffer.resize(0); - - // Skip any empty strings - while (it != itEnd && it->empty()) - ++it; - - if (it != itEnd) { - auto const &next = *it; - if (isOptPrefix(next[0])) { - auto delimiterPos = next.find_first_of(" :="); - if (delimiterPos != std::string::npos) { - m_tokenBuffer.push_back( - {TokenType::Option, next.substr(0, delimiterPos)}); - m_tokenBuffer.push_back( - {TokenType::Argument, next.substr(delimiterPos + 1)}); - } - else { - if (next[1] != '-' && next.size() > 2) { - std::string opt = "- "; - for (size_t i = 1; i < next.size(); ++i) { - opt[1] = next[i]; - m_tokenBuffer.push_back({TokenType::Option, opt}); - } - } - else { - m_tokenBuffer.push_back({TokenType::Option, next}); - } - } - } - else { - m_tokenBuffer.push_back({TokenType::Argument, next}); - } - } - } - -public: - explicit TokenStream(Args const &args) - : TokenStream(args.m_args.begin(), args.m_args.end()) - { - } - - TokenStream(Iterator it, Iterator itEnd) - : it(it) - , itEnd(itEnd) - { - loadBuffer(); - } - - explicit operator bool() const - { - return !m_tokenBuffer.empty() || it != itEnd; - } - - auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } - - auto operator*() const -> Token - { - assert(!m_tokenBuffer.empty()); - return m_tokenBuffer.front(); - } - - auto operator->() const -> Token const * - { - assert(!m_tokenBuffer.empty()); - return &m_tokenBuffer.front(); - } - - auto operator++() -> TokenStream & - { - if (m_tokenBuffer.size() >= 2) { - m_tokenBuffer.erase(m_tokenBuffer.begin()); - } - else { - if (it != itEnd) - ++it; - loadBuffer(); - } - return *this; - } -}; - -class ResultBase { -public: - enum Type { Ok, LogicError, RuntimeError }; - -protected: - ResultBase(Type type) - : m_type(type) - { - } - virtual ~ResultBase() = default; - - virtual void enforceOk() const = 0; - - Type m_type; -}; - -template class ResultValueBase : public ResultBase { -public: - auto value() const -> T const & - { - enforceOk(); - return m_value; - } - -protected: - ResultValueBase(Type type) - : ResultBase(type) - { - } - - ResultValueBase(ResultValueBase const &other) - : ResultBase(other) - { - if (m_type == ResultBase::Ok) - new (&m_value) T(other.m_value); - } - - ResultValueBase(Type, T const &value) - : ResultBase(Ok) - { - new (&m_value) T(value); - } - - auto operator=(ResultValueBase const &other) -> ResultValueBase & - { - if (m_type == ResultBase::Ok) - m_value.~T(); - ResultBase::operator=(other); - if (m_type == ResultBase::Ok) - new (&m_value) T(other.m_value); - return *this; - } - - ~ResultValueBase() override - { - if (m_type == Ok) - m_value.~T(); - } - - union { - T m_value; - }; -}; - -template <> class ResultValueBase : public ResultBase { -protected: - using ResultBase::ResultBase; -}; - -template class BasicResult : public ResultValueBase { -public: - template - explicit BasicResult(BasicResult const &other) - : ResultValueBase(other.type()) - , m_errorMessage(other.errorMessage()) - { - assert(type() != ResultBase::Ok); - } - - template static auto ok(U const &value) -> BasicResult - { - return {ResultBase::Ok, value}; - } - static auto ok() -> BasicResult { return {ResultBase::Ok}; } - static auto logicError(std::string const &message) -> BasicResult - { - return {ResultBase::LogicError, message}; - } - static auto runtimeError(std::string const &message) -> BasicResult - { - return {ResultBase::RuntimeError, message}; - } - - explicit operator bool() const { return m_type == ResultBase::Ok; } - auto type() const -> ResultBase::Type { return m_type; } - auto errorMessage() const -> std::string { return m_errorMessage; } - -protected: - void enforceOk() const override - { - - // Errors shouldn't reach this point, but if they do - // the actual error message will be in m_errorMessage - assert(m_type != ResultBase::LogicError); - assert(m_type != ResultBase::RuntimeError); - if (m_type != ResultBase::Ok) - std::abort(); - } - - std::string m_errorMessage; // Only populated if resultType is an error - - BasicResult(ResultBase::Type type, std::string const &message) - : ResultValueBase(type) - , m_errorMessage(message) - { - assert(m_type != ResultBase::Ok); - } - - using ResultValueBase::ResultValueBase; - using ResultBase::m_type; -}; - -enum class ParseResultType { - Matched, - NoMatch, - ShortCircuitAll, - ShortCircuitSame -}; - -class ParseState { -public: - ParseState(ParseResultType type, TokenStream const &remainingTokens) - : m_type(type) - , m_remainingTokens(remainingTokens) - { - } - - auto type() const -> ParseResultType { return m_type; } - auto remainingTokens() const -> TokenStream { return m_remainingTokens; } - -private: - ParseResultType m_type; - TokenStream m_remainingTokens; -}; - -using Result = BasicResult; -using ParserResult = BasicResult; -using InternalParseResult = BasicResult; - -struct HelpColumns { - std::string left; - std::string right; -}; - -template -inline auto convertInto(std::string const &source, T &target) -> ParserResult -{ - std::stringstream ss; - ss << source; - ss >> target; - if (ss.fail()) - return ParserResult::runtimeError( - "Unable to convert '" + source + "' to destination type"); - else - return ParserResult::ok(ParseResultType::Matched); -} -inline auto convertInto(std::string const &source, std::string &target) - -> ParserResult -{ - target = source; - return ParserResult::ok(ParseResultType::Matched); -} -inline auto convertInto(std::string const &source, bool &target) -> ParserResult -{ - std::string srcLC = source; - std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), - [](unsigned char c) { return static_cast(std::tolower(c)); }); - if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || - srcLC == "on") - target = true; - else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || - srcLC == "no" || srcLC == "off") - target = false; - else - return ParserResult::runtimeError( - "Expected a boolean value but did not recognise: '" + source + "'"); - return ParserResult::ok(ParseResultType::Matched); -} -#ifdef CLARA_CONFIG_OPTIONAL_TYPE -template -inline auto convertInto(std::string const &source, - CLARA_CONFIG_OPTIONAL_TYPE &target) -> ParserResult -{ - T temp; - auto result = convertInto(source, temp); - if (result) - target = std::move(temp); - return result; -} -#endif // CLARA_CONFIG_OPTIONAL_TYPE - -struct NonCopyable { - NonCopyable() = default; - NonCopyable(NonCopyable const &) = delete; - NonCopyable(NonCopyable &&) = delete; - NonCopyable &operator=(NonCopyable const &) = delete; - NonCopyable &operator=(NonCopyable &&) = delete; -}; - -struct BoundRef : NonCopyable { - virtual ~BoundRef() = default; - virtual auto isContainer() const -> bool { return false; } - virtual auto isFlag() const -> bool { return false; } -}; -struct BoundValueRefBase : BoundRef { - virtual auto setValue(std::string const &arg) -> ParserResult = 0; -}; -struct BoundFlagRefBase : BoundRef { - virtual auto setFlag(bool flag) -> ParserResult = 0; - virtual auto isFlag() const -> bool { return true; } -}; - -template struct BoundValueRef : BoundValueRefBase { - T &m_ref; - - explicit BoundValueRef(T &ref) - : m_ref(ref) - { - } - - auto setValue(std::string const &arg) -> ParserResult override - { - return convertInto(arg, m_ref); - } -}; - -template struct BoundValueRef> : BoundValueRefBase { - std::vector &m_ref; - - explicit BoundValueRef(std::vector &ref) - : m_ref(ref) - { - } - - auto isContainer() const -> bool override { return true; } - - auto setValue(std::string const &arg) -> ParserResult override - { - T temp; - auto result = convertInto(arg, temp); - if (result) - m_ref.push_back(temp); - return result; - } -}; - -struct BoundFlagRef : BoundFlagRefBase { - bool &m_ref; - - explicit BoundFlagRef(bool &ref) - : m_ref(ref) - { - } - - auto setFlag(bool flag) -> ParserResult override - { - m_ref = flag; - return ParserResult::ok(ParseResultType::Matched); - } -}; - -template struct LambdaInvoker { - static_assert(std::is_same::value, - "Lambda must return void or clara::ParserResult"); - - template - static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult - { - return lambda(arg); - } -}; - -template <> struct LambdaInvoker { - template - static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult - { - lambda(arg); - return ParserResult::ok(ParseResultType::Matched); - } -}; - -template -inline auto invokeLambda(L const &lambda, std::string const &arg) - -> ParserResult -{ - ArgType temp{}; - auto result = convertInto(arg, temp); - return !result - ? result - : LambdaInvoker::ReturnType>::invoke( - lambda, temp); -} - -template struct BoundLambda : BoundValueRefBase { - L m_lambda; - - static_assert(UnaryLambdaTraits::isValid, - "Supplied lambda must take exactly one argument"); - explicit BoundLambda(L const &lambda) - : m_lambda(lambda) - { - } - - auto setValue(std::string const &arg) -> ParserResult override - { - return invokeLambda::ArgType>( - m_lambda, arg); - } -}; - -template struct BoundFlagLambda : BoundFlagRefBase { - L m_lambda; - - static_assert(UnaryLambdaTraits::isValid, - "Supplied lambda must take exactly one argument"); - static_assert( - std::is_same::ArgType, bool>::value, - "flags must be boolean"); - - explicit BoundFlagLambda(L const &lambda) - : m_lambda(lambda) - { - } - - auto setFlag(bool flag) -> ParserResult override - { - return LambdaInvoker::ReturnType>::invoke( - m_lambda, flag); - } -}; - -enum class Optionality { Optional, Required }; - -struct Parser; - -class ParserBase { -public: - virtual ~ParserBase() = default; - virtual auto validate() const -> Result { return Result::ok(); } - virtual auto parse(std::string const &exeName, - TokenStream const &tokens) const -> InternalParseResult = 0; - virtual auto cardinality() const -> size_t { return 1; } - - auto parse(Args const &args) const -> InternalParseResult - { - return parse(args.exeName(), TokenStream(args)); - } -}; - -template class ComposableParserImpl : public ParserBase { -public: - template auto operator|(T const &other) const -> Parser; - - template auto operator+(T const &other) const -> Parser; -}; - -// Common code and state for Args and Opts -template -class ParserRefImpl : public ComposableParserImpl { -protected: - Optionality m_optionality = Optionality::Optional; - std::shared_ptr m_ref; - std::string m_hint; - std::string m_description; - - explicit ParserRefImpl(std::shared_ptr const &ref) - : m_ref(ref) - { - } - -public: - template - ParserRefImpl(T &ref, std::string const &hint) - : m_ref(std::make_shared>(ref)) - , m_hint(hint) - { - } - - template - ParserRefImpl(LambdaT const &ref, std::string const &hint) - : m_ref(std::make_shared>(ref)) - , m_hint(hint) - { - } - - auto operator()(std::string const &description) -> DerivedT & - { - m_description = description; - return static_cast(*this); - } - - auto optional() -> DerivedT & - { - m_optionality = Optionality::Optional; - return static_cast(*this); - }; - - auto required() -> DerivedT & - { - m_optionality = Optionality::Required; - return static_cast(*this); - }; - - auto isOptional() const -> bool - { - return m_optionality == Optionality::Optional; - } - - auto cardinality() const -> size_t override - { - if (m_ref->isContainer()) - return 0; - else - return 1; - } - - auto hint() const -> std::string { return m_hint; } -}; - -class ExeName : public ComposableParserImpl { - std::shared_ptr m_name; - std::shared_ptr m_ref; - - template - static auto makeRef(LambdaT const &lambda) - -> std::shared_ptr - { - return std::make_shared>(lambda); - } - -public: - ExeName() - : m_name(std::make_shared("")) - { - } - - explicit ExeName(std::string &ref) - : ExeName() - { - m_ref = std::make_shared>(ref); - } - - template - explicit ExeName(LambdaT const &lambda) - : ExeName() - { - m_ref = std::make_shared>(lambda); - } - - // The exe name is not parsed out of the normal tokens, but is handled - // specially - auto parse(std::string const &, TokenStream const &tokens) const - -> InternalParseResult override - { - return InternalParseResult::ok( - ParseState(ParseResultType::NoMatch, tokens)); - } - - auto name() const -> std::string { return *m_name; } - auto set(std::string const &newName) -> ParserResult - { - - auto lastSlash = newName.find_last_of("\\/"); - auto filename = (lastSlash == std::string::npos) - ? newName - : newName.substr(lastSlash + 1); - - *m_name = filename; - if (m_ref) - return m_ref->setValue(filename); - else - return ParserResult::ok(ParseResultType::Matched); - } -}; - -class Arg : public ParserRefImpl { -public: - using ParserRefImpl::ParserRefImpl; - - auto parse(std::string const &, TokenStream const &tokens) const - -> InternalParseResult override - { - auto validationResult = validate(); - if (!validationResult) - return InternalParseResult(validationResult); - - auto remainingTokens = tokens; - auto const &token = *remainingTokens; - if (token.type != TokenType::Argument) - return InternalParseResult::ok( - ParseState(ParseResultType::NoMatch, remainingTokens)); - - assert(!m_ref->isFlag()); - auto valueRef = static_cast(m_ref.get()); - - auto result = valueRef->setValue(remainingTokens->token); - if (!result) - return InternalParseResult(result); - else - return InternalParseResult::ok( - ParseState(ParseResultType::Matched, ++remainingTokens)); - } -}; - -inline auto normaliseOpt(std::string const &optName) -> std::string -{ -#ifdef CATCH_PLATFORM_WINDOWS - if (optName[0] == '/') - return "-" + optName.substr(1); - else -#endif - return optName; -} - -class Opt : public ParserRefImpl { -protected: - std::vector m_optNames; - -public: - template - explicit Opt(LambdaT const &ref) - : ParserRefImpl(std::make_shared>(ref)) - { - } - - explicit Opt(bool &ref) - : ParserRefImpl(std::make_shared(ref)) - { - } - - template - Opt(LambdaT const &ref, std::string const &hint) - : ParserRefImpl(ref, hint) - { - } - - template - Opt(T &ref, std::string const &hint) - : ParserRefImpl(ref, hint) - { - } - - auto operator[](std::string const &optName) -> Opt & - { - m_optNames.push_back(optName); - return *this; - } - - auto getHelpColumns() const -> std::vector - { - std::ostringstream oss; - bool first = true; - for (auto const &opt : m_optNames) { - if (first) - first = false; - else - oss << ", "; - oss << opt; - } - if (!m_hint.empty()) - oss << " <" << m_hint << ">"; - return {{oss.str(), m_description}}; - } - - auto isMatch(std::string const &optToken) const -> bool - { - auto normalisedToken = normaliseOpt(optToken); - for (auto const &name : m_optNames) { - if (normaliseOpt(name) == normalisedToken) - return true; - } - return false; - } - - using ParserBase::parse; - - auto parse(std::string const &, TokenStream const &tokens) const - -> InternalParseResult override - { - auto validationResult = validate(); - if (!validationResult) - return InternalParseResult(validationResult); - - auto remainingTokens = tokens; - if (remainingTokens && remainingTokens->type == TokenType::Option) { - auto const &token = *remainingTokens; - if (isMatch(token.token)) { - if (m_ref->isFlag()) { - auto flagRef = - static_cast(m_ref.get()); - auto result = flagRef->setFlag(true); - if (!result) - return InternalParseResult(result); - if (result.value() == ParseResultType::ShortCircuitAll) - return InternalParseResult::ok( - ParseState(result.value(), remainingTokens)); - } - else { - auto valueRef = - static_cast(m_ref.get()); - ++remainingTokens; - if (!remainingTokens) - return InternalParseResult::runtimeError( - "Expected argument following " + token.token); - auto const &argToken = *remainingTokens; - if (argToken.type != TokenType::Argument) - return InternalParseResult::runtimeError( - "Expected argument following " + token.token); - auto result = valueRef->setValue(argToken.token); - if (!result) - return InternalParseResult(result); - if (result.value() == ParseResultType::ShortCircuitAll) - return InternalParseResult::ok( - ParseState(result.value(), remainingTokens)); - } - return InternalParseResult::ok( - ParseState(ParseResultType::Matched, ++remainingTokens)); - } - } - return InternalParseResult::ok( - ParseState(ParseResultType::NoMatch, remainingTokens)); - } - - auto validate() const -> Result override - { - if (m_optNames.empty()) - return Result::logicError("No options supplied to Opt"); - for (auto const &name : m_optNames) { - if (name.empty()) - return Result::logicError("Option name cannot be empty"); -#ifdef CATCH_PLATFORM_WINDOWS - if (name[0] != '-' && name[0] != '/') - return Result::logicError( - "Option name must begin with '-' or '/'"); -#else - if (name[0] != '-') - return Result::logicError("Option name must begin with '-'"); -#endif - } - return ParserRefImpl::validate(); - } -}; - -struct Help : Opt { - Help(bool &showHelpFlag) - : Opt([&](bool flag) { - showHelpFlag = flag; - return ParserResult::ok(ParseResultType::ShortCircuitAll); - }) - { - static_cast(*this)( - "display usage information")["-?"]["-h"]["--help"] - .optional(); - } -}; - -struct Parser : ParserBase { - - mutable ExeName m_exeName; - std::vector m_options; - std::vector m_args; - - auto operator|=(ExeName const &exeName) -> Parser & - { - m_exeName = exeName; - return *this; - } - - auto operator|=(Arg const &arg) -> Parser & - { - m_args.push_back(arg); - return *this; - } - - auto operator|=(Opt const &opt) -> Parser & - { - m_options.push_back(opt); - return *this; - } - - auto operator|=(Parser const &other) -> Parser & - { - m_options.insert( - m_options.end(), other.m_options.begin(), other.m_options.end()); - m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); - return *this; - } - - template auto operator|(T const &other) const -> Parser - { - return Parser(*this) |= other; - } - - // Forward deprecated interface with '+' instead of '|' - template auto operator+=(T const &other) -> Parser & - { - return operator|=(other); - } - template auto operator+(T const &other) const -> Parser - { - return operator|(other); - } - - auto getHelpColumns() const -> std::vector - { - std::vector cols; - for (auto const &o : m_options) { - auto childCols = o.getHelpColumns(); - cols.insert(cols.end(), childCols.begin(), childCols.end()); - } - return cols; - } - - void writeToStream(std::ostream &os) const - { - if (!m_exeName.name().empty()) { - os << "usage:\n" - << " " << m_exeName.name() << " "; - bool required = true, first = true; - for (auto const &arg : m_args) { - if (first) - first = false; - else - os << " "; - if (arg.isOptional() && required) { - os << "["; - required = false; - } - os << "<" << arg.hint() << ">"; - if (arg.cardinality() == 0) - os << " ... "; - } - if (!required) - os << "]"; - if (!m_options.empty()) - os << " options"; - os << "\n\nwhere options are:" << std::endl; - } - - auto rows = getHelpColumns(); - size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; - size_t optWidth = 0; - for (auto const &cols : rows) - optWidth = (std::max)(optWidth, cols.left.size() + 2); - - optWidth = (std::min)(optWidth, consoleWidth / 2); - - for (auto const &cols : rows) { - auto row = TextFlow::Column(cols.left).width(optWidth).indent(2) + - TextFlow::Spacer(4) + - TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); - os << row << std::endl; - } - } - - friend auto operator<<(std::ostream &os, Parser const &parser) - -> std::ostream & - { - parser.writeToStream(os); - return os; - } - - auto validate() const -> Result override - { - for (auto const &opt : m_options) { - auto result = opt.validate(); - if (!result) - return result; - } - for (auto const &arg : m_args) { - auto result = arg.validate(); - if (!result) - return result; - } - return Result::ok(); - } - - using ParserBase::parse; - - auto parse(std::string const &exeName, TokenStream const &tokens) const - -> InternalParseResult override - { - - struct ParserInfo { - ParserBase const *parser = nullptr; - size_t count = 0; - }; - const size_t totalParsers = m_options.size() + m_args.size(); - assert(totalParsers < 512); - // ParserInfo parseInfos[totalParsers]; // <-- this is what we really - // want to do - ParserInfo parseInfos[512]; - - { - size_t i = 0; - for (auto const &opt : m_options) - parseInfos[i++].parser = &opt; - for (auto const &arg : m_args) - parseInfos[i++].parser = &arg; - } - - m_exeName.set(exeName); - - auto result = InternalParseResult::ok( - ParseState(ParseResultType::NoMatch, tokens)); - while (result.value().remainingTokens()) { - bool tokenParsed = false; - - for (size_t i = 0; i < totalParsers; ++i) { - auto &parseInfo = parseInfos[i]; - if (parseInfo.parser->cardinality() == 0 || - parseInfo.count < parseInfo.parser->cardinality()) { - result = parseInfo.parser->parse( - exeName, result.value().remainingTokens()); - if (!result) - return result; - if (result.value().type() != ParseResultType::NoMatch) { - tokenParsed = true; - ++parseInfo.count; - break; - } - } - } - - if (result.value().type() == ParseResultType::ShortCircuitAll) - return result; - if (!tokenParsed) - return InternalParseResult::runtimeError( - "Unrecognised token: " + - result.value().remainingTokens()->token); - } - // !TBD Check missing required options - return result; - } -}; - -template -template -auto ComposableParserImpl::operator|(T const &other) const -> Parser -{ - return Parser() | static_cast(*this) | other; -} -} // namespace detail - -// A Combined parser -using detail::Parser; - -// A parser for options -using detail::Opt; - -// A parser for arguments -using detail::Arg; - -// Wrapper for argc, argv from main() -using detail::Args; - -// Specifies the name of the executable -using detail::ExeName; - -// Convenience wrapper for option parser that specifies the help option -using detail::Help; - -// enum of result types from a parse -using detail::ParseResultType; - -// Result type for parser operation -using detail::ParserResult; - -} -} // namespace Catch::clara - -// end clara.hpp -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// Restore Clara's value for console width, if present -#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH \ - CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#endif - -// end catch_clara.h -namespace Catch { - -clara::Parser makeCommandLineParser(ConfigData &config); - -} // end namespace Catch - -// end catch_commandline.h -#include -#include - -namespace Catch { - -clara::Parser makeCommandLineParser(ConfigData &config) -{ - - using namespace clara; - - auto const setWarning = [&](std::string const &warning) { - auto warningSet = [&]() { - if (warning == "NoAssertions") - return WarnAbout::NoAssertions; - - if (warning == "NoTests") - return WarnAbout::NoTests; - - return WarnAbout::Nothing; - }(); - - if (warningSet == WarnAbout::Nothing) - return ParserResult::runtimeError( - "Unrecognised warning: '" + warning + "'"); - config.warnings = - static_cast(config.warnings | warningSet); - return ParserResult::ok(ParseResultType::Matched); - }; - auto const loadTestNamesFromFile = [&](std::string const &filename) { - std::ifstream f(filename.c_str()); - if (!f.is_open()) - return ParserResult::runtimeError( - "Unable to load input file: '" + filename + "'"); - - std::string line; - while (std::getline(f, line)) { - line = trim(line); - if (!line.empty() && !startsWith(line, '#')) { - if (!startsWith(line, '"')) - line = '"' + line + '"'; - config.testsOrTags.push_back(line); - config.testsOrTags.emplace_back(","); - } - } - // Remove comma in the end - if (!config.testsOrTags.empty()) - config.testsOrTags.erase(config.testsOrTags.end() - 1); - - return ParserResult::ok(ParseResultType::Matched); - }; - auto const setTestOrder = [&](std::string const &order) { - if (startsWith("declared", order)) - config.runOrder = RunTests::InDeclarationOrder; - else if (startsWith("lexical", order)) - config.runOrder = RunTests::InLexicographicalOrder; - else if (startsWith("random", order)) - config.runOrder = RunTests::InRandomOrder; - else - return clara::ParserResult::runtimeError( - "Unrecognised ordering: '" + order + "'"); - return ParserResult::ok(ParseResultType::Matched); - }; - auto const setRngSeed = [&](std::string const &seed) { - if (seed != "time") - return clara::detail::convertInto(seed, config.rngSeed); - config.rngSeed = static_cast(std::time(nullptr)); - return ParserResult::ok(ParseResultType::Matched); - }; - auto const setColourUsage = [&](std::string const &useColour) { - auto mode = toLower(useColour); - - if (mode == "yes") - config.useColour = UseColour::Yes; - else if (mode == "no") - config.useColour = UseColour::No; - else if (mode == "auto") - config.useColour = UseColour::Auto; - else - return ParserResult::runtimeError( - "colour mode must be one of: auto, yes or no. '" + useColour + - "' not recognised"); - return ParserResult::ok(ParseResultType::Matched); - }; - auto const setWaitForKeypress = [&](std::string const &keypress) { - auto keypressLc = toLower(keypress); - if (keypressLc == "never") - config.waitForKeypress = WaitForKeypress::Never; - else if (keypressLc == "start") - config.waitForKeypress = WaitForKeypress::BeforeStart; - else if (keypressLc == "exit") - config.waitForKeypress = WaitForKeypress::BeforeExit; - else if (keypressLc == "both") - config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; - else - return ParserResult::runtimeError( - "keypress argument must be one of: never, start, exit or both. " - "'" + - keypress + "' not recognised"); - return ParserResult::ok(ParseResultType::Matched); - }; - auto const setVerbosity = [&](std::string const &verbosity) { - auto lcVerbosity = toLower(verbosity); - if (lcVerbosity == "quiet") - config.verbosity = Verbosity::Quiet; - else if (lcVerbosity == "normal") - config.verbosity = Verbosity::Normal; - else if (lcVerbosity == "high") - config.verbosity = Verbosity::High; - else - return ParserResult::runtimeError( - "Unrecognised verbosity, '" + verbosity + "'"); - return ParserResult::ok(ParseResultType::Matched); - }; - auto const setReporter = [&](std::string const &reporter) { - IReporterRegistry::FactoryMap const &factories = - getRegistryHub().getReporterRegistry().getFactories(); - - auto lcReporter = toLower(reporter); - auto result = factories.find(lcReporter); - - if (factories.end() != result) - config.reporterName = lcReporter; - else - return ParserResult::runtimeError("Unrecognized reporter, '" + - reporter + "'. Check available with --list-reporters"); - return ParserResult::ok(ParseResultType::Matched); - }; - - auto cli = ExeName(config.processName) | Help(config.showHelp) | - Opt(config.listTests)["-l"]["--list-tests"]( - "list all/matching test cases") | - Opt(config.listTags)["-t"]["--list-tags"]("list all/matching tags") | - Opt(config.showSuccessfulTests)["-s"]["--success"]( - "include successful tests in output") | - Opt(config.shouldDebugBreak)["-b"]["--break"]( - "break into debugger on failure") | - Opt(config.noThrow)["-e"]["--nothrow"]("skip exception tests") | - Opt(config.showInvisibles)["-i"]["--invisibles"]( - "show invisibles (tabs, newlines)") | - Opt(config.outputFilename, "filename")["-o"]["--out"]( - "output filename") | - Opt(setReporter, "name")["-r"]["--reporter"]( - "reporter to use (defaults to console)") | - Opt(config.name, "name")["-n"]["--name"]("suite name") | Opt([&](bool) { - config.abortAfter = 1; - })["-a"]["--abort"]("abort at first failure") | - Opt([&](int x) { config.abortAfter = x; }, - "no. failures")["-x"]["--abortx"]("abort after x failures") | - Opt(setWarning, "warning name")["-w"]["--warn"]("enable warnings") | - Opt( - [&](bool flag) { - config.showDurations = - flag ? ShowDurations::Always : ShowDurations::Never; - }, - "yes|no")["-d"]["--durations"]("show test durations") | - Opt(config.minDuration, "seconds")["-D"]["--min-duration"]( - "show test durations for tests taking at least the given number of " - "seconds") | - Opt(loadTestNamesFromFile, "filename")["-f"]["--input-file"]( - "load test names to run from a file") | - Opt(config.filenamesAsTags)["-#"]["--filenames-as-tags"]( - "adds a tag for the filename") | - Opt(config.sectionsToRun, "section name")["-c"]["--section"]( - "specify section to run") | - Opt(setVerbosity, "quiet|normal|high")["-v"]["--verbosity"]( - "set output verbosity") | - Opt(config.listTestNamesOnly)["--list-test-names-only"]( - "list all/matching test cases names only") | - Opt(config.listReporters)["--list-reporters"]("list all reporters") | - Opt(setTestOrder, "decl|lex|rand")["--order"]( - "test case order (defaults to decl)") | - Opt(setRngSeed, "'time'|number")["--rng-seed"]( - "set a specific seed for random numbers") | - Opt(setColourUsage, "yes|no")["--use-colour"]( - "should output be colourised") | - Opt(config.libIdentify)["--libidentify"]( - "report name and version according to libidentify standard") | - Opt(setWaitForKeypress, "never|start|exit|both")["--wait-for-keypress"]( - "waits for a keypress before exiting") | - Opt(config.benchmarkSamples, "samples")["--benchmark-samples"]( - "number of samples to collect (default: 100)") | - Opt(config.benchmarkResamples, "resamples")["--benchmark-resamples"]( - "number of resamples for the bootstrap (default: 100000)") | - Opt(config.benchmarkConfidenceInterval, - "confidence interval")["--benchmark-confidence-interval"]( - "confidence interval for the bootstrap (between 0 and 1, default: " - "0.95)") | - Opt(config.benchmarkNoAnalysis)["--benchmark-no-analysis"]( - "perform only measurements; do not perform any analysis") | - Opt(config.benchmarkWarmupTime, - "benchmarkWarmupTime")["--benchmark-warmup-time"]( - "amount of time in milliseconds spent on warming up each test " - "(default: 100)") | - Arg(config.testsOrTags, "test name|pattern|tags")( - "which test or tests to use"); - - return cli; -} - -} // end namespace Catch -// end catch_commandline.cpp -// start catch_common.cpp - -#include -#include - -namespace Catch { - -bool SourceLineInfo::operator==(SourceLineInfo const &other) const noexcept -{ - return line == other.line && - (file == other.file || std::strcmp(file, other.file) == 0); -} -bool SourceLineInfo::operator<(SourceLineInfo const &other) const noexcept -{ - // We can assume that the same file will usually have the same pointer. - // Thus, if the pointers are the same, there is no point in calling the - // strcmp - return line < other.line || - (line == other.line && file != other.file && - (std::strcmp(file, other.file) < 0)); -} - -std::ostream &operator<<(std::ostream &os, SourceLineInfo const &info) -{ -#ifndef __GNUG__ - os << info.file << '(' << info.line << ')'; -#else - os << info.file << ':' << info.line; -#endif - return os; -} - -std::string StreamEndStop::operator+() const { return std::string(); } - -NonCopyable::NonCopyable() = default; -NonCopyable::~NonCopyable() = default; - -} -// end catch_common.cpp -// start catch_config.cpp - -namespace Catch { - -Config::Config(ConfigData const &data) - : m_data(data) - , m_stream(openStream()) -{ - // We need to trim filter specs to avoid trouble with superfluous - // whitespace (esp. important for bdd macros, as those are manually - // aligned with whitespace). - - for (auto &elem : m_data.testsOrTags) { - elem = trim(elem); - } - for (auto &elem : m_data.sectionsToRun) { - elem = trim(elem); - } - - TestSpecParser parser(ITagAliasRegistry::get()); - if (!m_data.testsOrTags.empty()) { - m_hasTestFilters = true; - for (auto const &testOrTags : m_data.testsOrTags) { - parser.parse(testOrTags); - } - } - m_testSpec = parser.testSpec(); -} - -std::string const &Config::getFilename() const { return m_data.outputFilename; } - -bool Config::listTests() const { return m_data.listTests; } -bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } -bool Config::listTags() const { return m_data.listTags; } -bool Config::listReporters() const { return m_data.listReporters; } - -std::string Config::getProcessName() const { return m_data.processName; } -std::string const &Config::getReporterName() const -{ - return m_data.reporterName; -} - -std::vector const &Config::getTestsOrTags() const -{ - return m_data.testsOrTags; -} -std::vector const &Config::getSectionsToRun() const -{ - return m_data.sectionsToRun; -} - -TestSpec const &Config::testSpec() const { return m_testSpec; } -bool Config::hasTestFilters() const { return m_hasTestFilters; } - -bool Config::showHelp() const { return m_data.showHelp; } - -// IConfig interface -bool Config::allowThrows() const { return !m_data.noThrow; } -std::ostream &Config::stream() const { return m_stream->stream(); } -std::string Config::name() const -{ - return m_data.name.empty() ? m_data.processName : m_data.name; -} -bool Config::includeSuccessfulResults() const -{ - return m_data.showSuccessfulTests; -} -bool Config::warnAboutMissingAssertions() const -{ - return !!(m_data.warnings & WarnAbout::NoAssertions); -} -bool Config::warnAboutNoTests() const -{ - return !!(m_data.warnings & WarnAbout::NoTests); -} -ShowDurations::OrNot Config::showDurations() const -{ - return m_data.showDurations; -} -double Config::minDuration() const { return m_data.minDuration; } -RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } -unsigned int Config::rngSeed() const { return m_data.rngSeed; } -UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } -bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } -int Config::abortAfter() const { return m_data.abortAfter; } -bool Config::showInvisibles() const { return m_data.showInvisibles; } -Verbosity Config::verbosity() const { return m_data.verbosity; } - -bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; } -int Config::benchmarkSamples() const { return m_data.benchmarkSamples; } -double Config::benchmarkConfidenceInterval() const -{ - return m_data.benchmarkConfidenceInterval; -} -unsigned int Config::benchmarkResamples() const -{ - return m_data.benchmarkResamples; -} -std::chrono::milliseconds Config::benchmarkWarmupTime() const -{ - return std::chrono::milliseconds(m_data.benchmarkWarmupTime); -} - -IStream const *Config::openStream() -{ - return Catch::makeStream(m_data.outputFilename); -} - -} // end namespace Catch -// end catch_config.cpp -// start catch_console_colour.cpp - -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wexit-time-destructors" -#endif - -// start catch_errno_guard.h - -namespace Catch { - -class ErrnoGuard { -public: - ErrnoGuard(); - ~ErrnoGuard(); - -private: - int m_oldErrno; -}; - -} - -// end catch_errno_guard.h -// start catch_windows_h_proxy.h - -#if defined(CATCH_PLATFORM_WINDOWS) - -#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -#define CATCH_DEFINED_NOMINMAX -#define NOMINMAX -#endif -#if !defined(WIN32_LEAN_AND_MEAN) && \ - !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -#define CATCH_DEFINED_WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -#ifdef CATCH_DEFINED_NOMINMAX -#undef NOMINMAX -#endif -#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN -#undef WIN32_LEAN_AND_MEAN -#endif - -#endif // defined(CATCH_PLATFORM_WINDOWS) - -// end catch_windows_h_proxy.h -#include - -namespace Catch { -namespace { - -struct IColourImpl { - virtual ~IColourImpl() = default; - virtual void use(Colour::Code _colourCode) = 0; -}; - -struct NoColourImpl : IColourImpl { - void use(Colour::Code) override { } - - static IColourImpl *instance() - { - static NoColourImpl s_instance; - return &s_instance; - } -}; - -} // anon namespace -} // namespace Catch - -#if !defined(CATCH_CONFIG_COLOUR_NONE) && \ - !defined(CATCH_CONFIG_COLOUR_WINDOWS) && \ - !defined(CATCH_CONFIG_COLOUR_ANSI) -#ifdef CATCH_PLATFORM_WINDOWS -#define CATCH_CONFIG_COLOUR_WINDOWS -#else -#define CATCH_CONFIG_COLOUR_ANSI -#endif -#endif - -#if defined( \ - CATCH_CONFIG_COLOUR_WINDOWS) ///////////////////////////////////////// - -namespace Catch { -namespace { - -class Win32ColourImpl : public IColourImpl { -public: - Win32ColourImpl() - : stdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)) - { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); - originalForegroundAttributes = csbiInfo.wAttributes & - ~(BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | - BACKGROUND_INTENSITY); - originalBackgroundAttributes = csbiInfo.wAttributes & - ~(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | - FOREGROUND_INTENSITY); - } - - void use(Colour::Code _colourCode) override - { - switch (_colourCode) { - case Colour::None: - return setTextAttribute(originalForegroundAttributes); - case Colour::White: - return setTextAttribute( - FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); - case Colour::Red: - return setTextAttribute(FOREGROUND_RED); - case Colour::Green: - return setTextAttribute(FOREGROUND_GREEN); - case Colour::Blue: - return setTextAttribute(FOREGROUND_BLUE); - case Colour::Cyan: - return setTextAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN); - case Colour::Yellow: - return setTextAttribute(FOREGROUND_RED | FOREGROUND_GREEN); - case Colour::Grey: - return setTextAttribute(0); - - case Colour::LightGrey: - return setTextAttribute(FOREGROUND_INTENSITY); - case Colour::BrightRed: - return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_RED); - case Colour::BrightGreen: - return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_GREEN); - case Colour::BrightWhite: - return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_GREEN | - FOREGROUND_RED | FOREGROUND_BLUE); - case Colour::BrightYellow: - return setTextAttribute( - FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN); - - case Colour::Bright: - CATCH_INTERNAL_ERROR("not a colour"); - - default: - CATCH_ERROR("Unknown colour requested"); - } - } - -private: - void setTextAttribute(WORD _textAttribute) - { - SetConsoleTextAttribute( - stdoutHandle, _textAttribute | originalBackgroundAttributes); - } - HANDLE stdoutHandle; - WORD originalForegroundAttributes; - WORD originalBackgroundAttributes; -}; - -IColourImpl *platformColourInstance() -{ - static Win32ColourImpl s_instance; - - IConfigPtr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = - config ? config->useColour() : UseColour::Auto; - if (colourMode == UseColour::Auto) - colourMode = UseColour::Yes; - return colourMode == UseColour::Yes ? &s_instance - : NoColourImpl::instance(); -} - -} // end anon namespace -} // end namespace Catch - -#elif defined(CATCH_CONFIG_COLOUR_ANSI) ////////////////////////////////////// - -#include - -namespace Catch { -namespace { - -// use POSIX/ ANSI console terminal codes -// Thanks to Adam Strzelecki for original contribution -// (http://github.com/nanoant) -// https://github.com/philsquared/Catch/pull/131 -class PosixColourImpl : public IColourImpl { -public: - void use(Colour::Code _colourCode) override - { - switch (_colourCode) { - case Colour::None: - case Colour::White: - return setColour("[0m"); - case Colour::Red: - return setColour("[0;31m"); - case Colour::Green: - return setColour("[0;32m"); - case Colour::Blue: - return setColour("[0;34m"); - case Colour::Cyan: - return setColour("[0;36m"); - case Colour::Yellow: - return setColour("[0;33m"); - case Colour::Grey: - return setColour("[1;30m"); - - case Colour::LightGrey: - return setColour("[0;37m"); - case Colour::BrightRed: - return setColour("[1;31m"); - case Colour::BrightGreen: - return setColour("[1;32m"); - case Colour::BrightWhite: - return setColour("[1;37m"); - case Colour::BrightYellow: - return setColour("[1;33m"); - - case Colour::Bright: - CATCH_INTERNAL_ERROR("not a colour"); - default: - CATCH_INTERNAL_ERROR("Unknown colour requested"); - } - } - static IColourImpl *instance() - { - static PosixColourImpl s_instance; - return &s_instance; - } - -private: - void setColour(const char *_escapeCode) - { - getCurrentContext().getConfig()->stream() << '\033' << _escapeCode; - } -}; - -bool useColourOnPlatform() -{ - return -#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) - !isDebuggerActive() && -#endif -#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) - isatty(STDOUT_FILENO) -#else - false -#endif - ; -} -IColourImpl *platformColourInstance() -{ - ErrnoGuard guard; - IConfigPtr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = - config ? config->useColour() : UseColour::Auto; - if (colourMode == UseColour::Auto) - colourMode = useColourOnPlatform() ? UseColour::Yes : UseColour::No; - return colourMode == UseColour::Yes ? PosixColourImpl::instance() - : NoColourImpl::instance(); -} - -} // end anon namespace -} // end namespace Catch - -#else // not Windows or ANSI /////////////////////////////////////////////// - -namespace Catch { - -static IColourImpl *platformColourInstance() -{ - return NoColourImpl::instance(); -} - -} // end namespace Catch - -#endif // Windows/ ANSI/ None - -namespace Catch { - -Colour::Colour(Code _colourCode) { use(_colourCode); } -Colour::Colour(Colour &&other) noexcept -{ - m_moved = other.m_moved; - other.m_moved = true; -} -Colour &Colour::operator=(Colour &&other) noexcept -{ - m_moved = other.m_moved; - other.m_moved = true; - return *this; -} - -Colour::~Colour() -{ - if (!m_moved) - use(None); -} - -void Colour::use(Code _colourCode) -{ - static IColourImpl *impl = platformColourInstance(); - // Strictly speaking, this cannot possibly happen. - // However, under some conditions it does happen (see #1626), - // and this change is small enough that we can let practicality - // triumph over purity in this case. - if (impl != nullptr) { - impl->use(_colourCode); - } -} - -std::ostream &operator<<(std::ostream &os, Colour const &) { return os; } - -} // end namespace Catch - -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - -// end catch_console_colour.cpp -// start catch_context.cpp - -namespace Catch { - -class Context : public IMutableContext, NonCopyable { - -public: // IContext - IResultCapture *getResultCapture() override { return m_resultCapture; } - IRunner *getRunner() override { return m_runner; } - - IConfigPtr const &getConfig() const override { return m_config; } - - ~Context() override; - -public: // IMutableContext - void setResultCapture(IResultCapture *resultCapture) override - { - m_resultCapture = resultCapture; - } - void setRunner(IRunner *runner) override { m_runner = runner; } - void setConfig(IConfigPtr const &config) override { m_config = config; } - - friend IMutableContext &getCurrentMutableContext(); - -private: - IConfigPtr m_config; - IRunner *m_runner = nullptr; - IResultCapture *m_resultCapture = nullptr; -}; - -IMutableContext *IMutableContext::currentContext = nullptr; - -void IMutableContext::createContext() { currentContext = new Context(); } - -void cleanUpContext() -{ - delete IMutableContext::currentContext; - IMutableContext::currentContext = nullptr; -} -IContext::~IContext() = default; -IMutableContext::~IMutableContext() = default; -Context::~Context() = default; - -SimplePcg32 &rng() -{ - static SimplePcg32 s_rng; - return s_rng; -} - -} -// end catch_context.cpp -// start catch_debug_console.cpp - -// start catch_debug_console.h - -#include - -namespace Catch { -void writeToDebugConsole(std::string const &text); -} - -// end catch_debug_console.h -#if defined(CATCH_CONFIG_ANDROID_LOGWRITE) -#include - -namespace Catch { -void writeToDebugConsole(std::string const &text) -{ - __android_log_write(ANDROID_LOG_DEBUG, "Catch", text.c_str()); -} -} - -#elif defined(CATCH_PLATFORM_WINDOWS) - -namespace Catch { -void writeToDebugConsole(std::string const &text) -{ - ::OutputDebugStringA(text.c_str()); -} -} - -#else - -namespace Catch { -void writeToDebugConsole(std::string const &text) -{ - // !TBD: Need a version for Mac/ XCode and other IDEs - Catch::cout() << text; -} -} - -#endif // Platform -// end catch_debug_console.cpp -// start catch_debugger.cpp - -#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) - -#include -#include -#include -#include -#include - -#ifdef __apple_build_version__ -// These headers will only compile with AppleClang (XCode) -// For other compilers (Clang, GCC, ... ) we need to exclude them -#include -#endif - -namespace Catch { -#ifdef __apple_build_version__ -// The following function is taken directly from the following technical note: -// https://developer.apple.com/library/archive/qa/qa1361/_index.html - -// Returns true if the current process is being debugged (either -// running under the debugger or has a debugger attached post facto). -bool isDebuggerActive() -{ - int mib[4]; - struct kinfo_proc info; - std::size_t size; - - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - - info.kp_proc.p_flag = 0; - - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - // Call sysctl. - - size = sizeof(info); - if (sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != - 0) { - Catch::cerr() << "\n** Call to sysctl failed - unable to determine if " - "debugger is active **\n" - << std::endl; - return false; - } - - // We're being debugged if the P_TRACED flag is set. - - return ((info.kp_proc.p_flag & P_TRACED) != 0); -} -#else -bool isDebuggerActive() -{ - // We need to find another way to determine this for non-appleclang - // compilers on macOS - return false; -} -#endif -} // namespace Catch - -#elif defined(CATCH_PLATFORM_LINUX) -#include -#include - -namespace Catch { -// The standard POSIX way of detecting a debugger is to attempt to -// ptrace() the process, but this needs to be done from a child and not -// this process itself to still allow attaching to this process later -// if wanted, so is rather heavy. Under Linux we have the PID of the -// "debugger" (which doesn't need to be gdb, of course, it could also -// be strace, for example) in /proc/$PID/status, so just get it from -// there instead. -bool isDebuggerActive() -{ - // Libstdc++ has a bug, where std::ifstream sets errno to 0 - // This way our users can properly assert over errno values - ErrnoGuard guard; - std::ifstream in("/proc/self/status"); - for (std::string line; std::getline(in, line);) { - static const int PREFIX_LEN = 11; - if (line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { - // We're traced if the PID is not 0 and no other PID starts - // with 0 digit, so it's enough to check for just a single - // character. - return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; - } - } - - return false; -} -} // namespace Catch -#elif defined(_MSC_VER) -extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); -namespace Catch { -bool isDebuggerActive() { return IsDebuggerPresent() != 0; } -} -#elif defined(__MINGW32__) -extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); -namespace Catch { -bool isDebuggerActive() { return IsDebuggerPresent() != 0; } -} -#else -namespace Catch { -bool isDebuggerActive() { return false; } -} -#endif // Platform -// end catch_debugger.cpp -// start catch_decomposer.cpp - -namespace Catch { - -ITransientExpression::~ITransientExpression() = default; - -void formatReconstructedExpression(std::ostream &os, std::string const &lhs, - StringRef op, std::string const &rhs) -{ - if (lhs.size() + rhs.size() < 40 && lhs.find('\n') == std::string::npos && - rhs.find('\n') == std::string::npos) - os << lhs << " " << op << " " << rhs; - else - os << lhs << "\n" << op << "\n" << rhs; -} -} -// end catch_decomposer.cpp -// start catch_enforce.cpp - -#include - -namespace Catch { -#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && \ - !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) -[[noreturn]] void throw_exception(std::exception const &e) -{ - Catch::cerr() - << "Catch will terminate because it needed to throw an exception.\n" - << "The message was: " << e.what() << '\n'; - std::terminate(); -} -#endif - -[[noreturn]] void throw_logic_error(std::string const &msg) -{ - throw_exception(std::logic_error(msg)); -} - -[[noreturn]] void throw_domain_error(std::string const &msg) -{ - throw_exception(std::domain_error(msg)); -} - -[[noreturn]] void throw_runtime_error(std::string const &msg) -{ - throw_exception(std::runtime_error(msg)); -} - -} // namespace Catch; -// end catch_enforce.cpp -// start catch_enum_values_registry.cpp -// start catch_enum_values_registry.h - -#include -#include - -namespace Catch { - -namespace Detail { - -std::unique_ptr makeEnumInfo(StringRef enumName, - StringRef allValueNames, std::vector const &values); - -class EnumValuesRegistry : public IMutableEnumValuesRegistry { - - std::vector> m_enumInfos; - - EnumInfo const ®isterEnum(StringRef enumName, StringRef allEnums, - std::vector const &values) override; -}; - -std::vector parseEnums(StringRef enums); - -} // Detail - -} // Catch - -// end catch_enum_values_registry.h - -#include -#include - -namespace Catch { - -IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() { } - -namespace Detail { - -namespace { -// Extracts the actual name part of an enum instance -// In other words, it returns the Blue part of Bikeshed::Colour::Blue -StringRef extractInstanceName(StringRef enumInstance) -{ - // Find last occurrence of ":" - size_t name_start = enumInstance.size(); - while (name_start > 0 && enumInstance[name_start - 1] != ':') { - --name_start; - } - return enumInstance.substr(name_start, enumInstance.size() - name_start); -} -} - -std::vector parseEnums(StringRef enums) -{ - auto enumValues = splitStringRef(enums, ','); - std::vector parsed; - parsed.reserve(enumValues.size()); - for (auto const &enumValue : enumValues) { - parsed.push_back(trim(extractInstanceName(enumValue))); - } - return parsed; -} - -EnumInfo::~EnumInfo() { } - -StringRef EnumInfo::lookup(int value) const -{ - for (auto const &valueToName : m_values) { - if (valueToName.first == value) - return valueToName.second; - } - return "{** unexpected enum value **}"_sr; -} - -std::unique_ptr makeEnumInfo( - StringRef enumName, StringRef allValueNames, std::vector const &values) -{ - std::unique_ptr enumInfo(new EnumInfo); - enumInfo->m_name = enumName; - enumInfo->m_values.reserve(values.size()); - - const auto valueNames = Catch::Detail::parseEnums(allValueNames); - assert(valueNames.size() == values.size()); - std::size_t i = 0; - for (auto value : values) - enumInfo->m_values.emplace_back(value, valueNames[i++]); - - return enumInfo; -} - -EnumInfo const &EnumValuesRegistry::registerEnum( - StringRef enumName, StringRef allValueNames, std::vector const &values) -{ - m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values)); - return *m_enumInfos.back(); -} - -} // Detail -} // Catch - -// end catch_enum_values_registry.cpp -// start catch_errno_guard.cpp - -#include - -namespace Catch { -ErrnoGuard::ErrnoGuard() - : m_oldErrno(errno) -{ -} -ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } -} -// end catch_errno_guard.cpp -// start catch_exception_translator_registry.cpp - -// start catch_exception_translator_registry.h - -#include -#include -#include - -namespace Catch { - -class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { -public: - ~ExceptionTranslatorRegistry(); - virtual void registerTranslator(const IExceptionTranslator *translator); - std::string translateActiveException() const override; - std::string tryTranslators() const; - -private: - std::vector> m_translators; -}; -} - -// end catch_exception_translator_registry.h -#ifdef __OBJC__ -#import "Foundation/Foundation.h" -#endif - -namespace Catch { - -ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { } - -void ExceptionTranslatorRegistry::registerTranslator( - const IExceptionTranslator *translator) -{ - m_translators.push_back( - std::unique_ptr(translator)); -} - -#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -std::string ExceptionTranslatorRegistry::translateActiveException() const -{ - try { -#ifdef __OBJC__ - // In Objective-C try objective-c exceptions first - @try { - return tryTranslators(); - } - @catch (NSException *exception) { - return Catch::Detail::stringify([exception description]); - } -#else - // Compiling a mixed mode project with MSVC means that CLR - // exceptions will be caught in (...) as well. However, these - // do not fill-in std::current_exception and thus lead to crash - // when attempting rethrow. - // /EHa switch also causes structured exceptions to be caught - // here, but they fill-in current_exception properly, so - // at worst the output should be a little weird, instead of - // causing a crash. - if (std::current_exception() == nullptr) { - return "Non C++ exception. Possibly a CLR exception."; - } - return tryTranslators(); -#endif - } - catch (TestFailureException &) { - std::rethrow_exception(std::current_exception()); - } - catch (std::exception &ex) { - return ex.what(); - } - catch (std::string &msg) { - return msg; - } - catch (const char *msg) { - return msg; - } - catch (...) { - return "Unknown exception"; - } -} - -std::string ExceptionTranslatorRegistry::tryTranslators() const -{ - if (m_translators.empty()) { - std::rethrow_exception(std::current_exception()); - } - else { - return m_translators[0]->translate( - m_translators.begin() + 1, m_translators.end()); - } -} - -#else // ^^ Exceptions are enabled // Exceptions are disabled vv -std::string ExceptionTranslatorRegistry::translateActiveException() const -{ - CATCH_INTERNAL_ERROR("Attempted to translate active exception under " - "CATCH_CONFIG_DISABLE_EXCEPTIONS!"); -} - -std::string ExceptionTranslatorRegistry::tryTranslators() const -{ - CATCH_INTERNAL_ERROR("Attempted to use exception translators under " - "CATCH_CONFIG_DISABLE_EXCEPTIONS!"); -} -#endif - -} -// end catch_exception_translator_registry.cpp -// start catch_fatal_condition.cpp - -#include - -#if !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_POSIX_SIGNALS) - -namespace Catch { - -// If neither SEH nor signal handling is required, the handler impls -// do not have to do anything, and can be empty. -void FatalConditionHandler::engage_platform() { } -void FatalConditionHandler::disengage_platform() { } -FatalConditionHandler::FatalConditionHandler() = default; -FatalConditionHandler::~FatalConditionHandler() = default; - -} // end namespace Catch - -#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS - -#if defined(CATCH_CONFIG_WINDOWS_SEH) && defined(CATCH_CONFIG_POSIX_SIGNALS) -#error \ - "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time" -#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS - -#if defined(CATCH_CONFIG_WINDOWS_SEH) || defined(CATCH_CONFIG_POSIX_SIGNALS) - -namespace { -//! Signals fatal error message to the run context -void reportFatal(char const *const message) -{ - Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( - message); -} - -//! Minimal size Catch2 needs for its own fatal error handling. -//! Picked anecdotally, so it might not be sufficient on all -//! platforms, and for all configurations. -constexpr std::size_t minStackSizeForErrors = 32 * 1024; -} // end unnamed namespace - -#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS - -#if defined(CATCH_CONFIG_WINDOWS_SEH) - -namespace Catch { - -struct SignalDefs { - DWORD id; - const char *name; -}; - -// There is no 1-1 mapping between signals and windows exceptions. -// Windows can easily distinguish between SO and SigSegV, -// but SigInt, SigTerm, etc are handled differently. -static SignalDefs signalDefs[] = { - {static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), - "SIGILL - Illegal instruction signal"}, - {static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, - {static_cast(EXCEPTION_ACCESS_VIOLATION), - "SIGSEGV - Segmentation violation signal"}, - {static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, -}; - -static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) -{ - for (auto const &def : signalDefs) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { - reportFatal(def.name); - } - } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; -} - -// Since we do not support multiple instantiations, we put these -// into global variables and rely on cleaning them up in outlined -// constructors/destructors -static PVOID exceptionHandlerHandle = nullptr; - -// For MSVC, we reserve part of the stack memory for handling -// memory overflow structured exception. -FatalConditionHandler::FatalConditionHandler() -{ - ULONG guaranteeSize = static_cast(minStackSizeForErrors); - if (!SetThreadStackGuarantee(&guaranteeSize)) { - // We do not want to fully error out, because needing - // the stack reserve should be rare enough anyway. - Catch::cerr() << "Failed to reserve piece of stack." - << " Stack overflows will not be reported successfully."; - } -} - -// We do not attempt to unset the stack guarantee, because -// Windows does not support lowering the stack size guarantee. -FatalConditionHandler::~FatalConditionHandler() = default; - -void FatalConditionHandler::engage_platform() -{ - // Register as first handler in current chain - exceptionHandlerHandle = - AddVectoredExceptionHandler(1, handleVectoredException); - if (!exceptionHandlerHandle) { - CATCH_RUNTIME_ERROR("Could not register vectored exception handler"); - } -} - -void FatalConditionHandler::disengage_platform() -{ - if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) { - CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler"); - } - exceptionHandlerHandle = nullptr; -} - -} // end namespace Catch - -#endif // CATCH_CONFIG_WINDOWS_SEH - -#if defined(CATCH_CONFIG_POSIX_SIGNALS) - -#include - -namespace Catch { - -struct SignalDefs { - int id; - const char *name; -}; - -static SignalDefs signalDefs[] = { - {SIGINT, "SIGINT - Terminal interrupt signal"}, - {SIGILL, "SIGILL - Illegal instruction signal"}, - {SIGFPE, "SIGFPE - Floating point error signal"}, - {SIGSEGV, "SIGSEGV - Segmentation violation signal"}, - {SIGTERM, "SIGTERM - Termination request signal"}, - {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}}; - -// Older GCCs trigger -Wmissing-field-initializers for T foo = {} -// which is zero initialization, but not explicit. We want to avoid -// that. -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif - -static char *altStackMem = nullptr; -static std::size_t altStackSize = 0; -static stack_t oldSigStack{}; -static struct sigaction - oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{}; - -static void restorePreviousSignalHandlers() -{ - // We set signal handlers back to the previous ones. Hopefully - // nobody overwrote them in the meantime, and doesn't expect - // their signal handlers to live past ours given that they - // installed them after ours.. - for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); - } - // Return the old stack - sigaltstack(&oldSigStack, nullptr); -} - -static void handleSignal(int sig) -{ - char const *name = ""; - for (auto const &def : signalDefs) { - if (sig == def.id) { - name = def.name; - break; - } - } - // We need to restore previous signal handlers and let them do - // their thing, so that the users can have the debugger break - // when a signal is raised, and so on. - restorePreviousSignalHandlers(); - reportFatal(name); - raise(sig); -} - -FatalConditionHandler::FatalConditionHandler() -{ - assert(!altStackMem && - "Cannot initialize POSIX signal handler when one already exists"); - if (altStackSize == 0) { - altStackSize = - std::max(static_cast(SIGSTKSZ), minStackSizeForErrors); - } - altStackMem = new char[altStackSize](); -} - -FatalConditionHandler::~FatalConditionHandler() -{ - delete[] altStackMem; - // We signal that another instance can be constructed by zeroing - // out the pointer. - altStackMem = nullptr; -} - -void FatalConditionHandler::engage_platform() -{ - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = altStackSize; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = {}; - - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } -} - -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - -void FatalConditionHandler::disengage_platform() -{ - restorePreviousSignalHandlers(); -} - -} // end namespace Catch - -#endif // CATCH_CONFIG_POSIX_SIGNALS -// end catch_fatal_condition.cpp -// start catch_generators.cpp - -#include -#include - -namespace Catch { - -IGeneratorTracker::~IGeneratorTracker() { } - -const char *GeneratorException::what() const noexcept { return m_msg; } - -namespace Generators { - -GeneratorUntypedBase::~GeneratorUntypedBase() { } - -auto acquireGeneratorTracker(StringRef generatorName, - SourceLineInfo const &lineInfo) -> IGeneratorTracker & -{ - return getResultCapture().acquireGeneratorTracker(generatorName, lineInfo); -} - -} // namespace Generators -} // namespace Catch -// end catch_generators.cpp -// start catch_interfaces_capture.cpp - -namespace Catch { -IResultCapture::~IResultCapture() = default; -} -// end catch_interfaces_capture.cpp -// start catch_interfaces_config.cpp - -namespace Catch { -IConfig::~IConfig() = default; -} -// end catch_interfaces_config.cpp -// start catch_interfaces_exception.cpp - -namespace Catch { -IExceptionTranslator::~IExceptionTranslator() = default; -IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; -} -// end catch_interfaces_exception.cpp -// start catch_interfaces_registry_hub.cpp - -namespace Catch { -IRegistryHub::~IRegistryHub() = default; -IMutableRegistryHub::~IMutableRegistryHub() = default; -} -// end catch_interfaces_registry_hub.cpp -// start catch_interfaces_reporter.cpp - -// start catch_reporter_listening.h - -namespace Catch { - -class ListeningReporter : public IStreamingReporter { - using Reporters = std::vector; - Reporters m_listeners; - IStreamingReporterPtr m_reporter = nullptr; - ReporterPreferences m_preferences; - -public: - ListeningReporter(); - - void addListener(IStreamingReporterPtr &&listener); - void addReporter(IStreamingReporterPtr &&reporter); - -public: // IStreamingReporter - ReporterPreferences getPreferences() const override; - - void noMatchingTestCases(std::string const &spec) override; - - void reportInvalidArguments(std::string const &arg) override; - - static std::set getSupportedVerbosities(); - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) - void benchmarkPreparing(std::string const &name) override; - void benchmarkStarting(BenchmarkInfo const &benchmarkInfo) override; - void benchmarkEnded(BenchmarkStats<> const &benchmarkStats) override; - void benchmarkFailed(std::string const &) override; -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - - void testRunStarting(TestRunInfo const &testRunInfo) override; - void testGroupStarting(GroupInfo const &groupInfo) override; - void testCaseStarting(TestCaseInfo const &testInfo) override; - void sectionStarting(SectionInfo const §ionInfo) override; - void assertionStarting(AssertionInfo const &assertionInfo) override; - - // The return value indicates if the messages buffer should be cleared: - bool assertionEnded(AssertionStats const &assertionStats) override; - void sectionEnded(SectionStats const §ionStats) override; - void testCaseEnded(TestCaseStats const &testCaseStats) override; - void testGroupEnded(TestGroupStats const &testGroupStats) override; - void testRunEnded(TestRunStats const &testRunStats) override; - - void skipTest(TestCaseInfo const &testInfo) override; - bool isMulti() const override; -}; - -} // end namespace Catch - -// end catch_reporter_listening.h -namespace Catch { - -ReporterConfig::ReporterConfig(IConfigPtr const &_fullConfig) - : m_stream(&_fullConfig->stream()) - , m_fullConfig(_fullConfig) -{ -} - -ReporterConfig::ReporterConfig( - IConfigPtr const &_fullConfig, std::ostream &_stream) - : m_stream(&_stream) - , m_fullConfig(_fullConfig) -{ -} - -std::ostream &ReporterConfig::stream() const { return *m_stream; } -IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } - -TestRunInfo::TestRunInfo(std::string const &_name) - : name(_name) -{ -} - -GroupInfo::GroupInfo( - std::string const &_name, std::size_t _groupIndex, std::size_t _groupsCount) - : name(_name) - , groupIndex(_groupIndex) - , groupsCounts(_groupsCount) -{ -} - -AssertionStats::AssertionStats(AssertionResult const &_assertionResult, - std::vector const &_infoMessages, Totals const &_totals) - : assertionResult(_assertionResult) - , infoMessages(_infoMessages) - , totals(_totals) -{ - assertionResult.m_resultData.lazyExpression.m_transientExpression = - _assertionResult.m_resultData.lazyExpression.m_transientExpression; - - if (assertionResult.hasMessage()) { - // Copy message into messages list. - // !TBD This should have been done earlier, somewhere - MessageBuilder builder(assertionResult.getTestMacroName(), - assertionResult.getSourceInfo(), assertionResult.getResultType()); - builder << assertionResult.getMessage(); - builder.m_info.message = builder.m_stream.str(); - - infoMessages.push_back(builder.m_info); - } -} - -AssertionStats::~AssertionStats() = default; - -SectionStats::SectionStats(SectionInfo const &_sectionInfo, - Counts const &_assertions, double _durationInSeconds, - bool _missingAssertions) - : sectionInfo(_sectionInfo) - , assertions(_assertions) - , durationInSeconds(_durationInSeconds) - , missingAssertions(_missingAssertions) -{ -} - -SectionStats::~SectionStats() = default; - -TestCaseStats::TestCaseStats(TestCaseInfo const &_testInfo, - Totals const &_totals, std::string const &_stdOut, - std::string const &_stdErr, bool _aborting) - : testInfo(_testInfo) - , totals(_totals) - , stdOut(_stdOut) - , stdErr(_stdErr) - , aborting(_aborting) -{ -} - -TestCaseStats::~TestCaseStats() = default; - -TestGroupStats::TestGroupStats( - GroupInfo const &_groupInfo, Totals const &_totals, bool _aborting) - : groupInfo(_groupInfo) - , totals(_totals) - , aborting(_aborting) -{ -} - -TestGroupStats::TestGroupStats(GroupInfo const &_groupInfo) - : groupInfo(_groupInfo) - , aborting(false) -{ -} - -TestGroupStats::~TestGroupStats() = default; - -TestRunStats::TestRunStats( - TestRunInfo const &_runInfo, Totals const &_totals, bool _aborting) - : runInfo(_runInfo) - , totals(_totals) - , aborting(_aborting) -{ -} - -TestRunStats::~TestRunStats() = default; - -void IStreamingReporter::fatalErrorEncountered(StringRef) { } -bool IStreamingReporter::isMulti() const { return false; } - -IReporterFactory::~IReporterFactory() = default; -IReporterRegistry::~IReporterRegistry() = default; - -} // end namespace Catch -// end catch_interfaces_reporter.cpp -// start catch_interfaces_runner.cpp - -namespace Catch { -IRunner::~IRunner() = default; -} -// end catch_interfaces_runner.cpp -// start catch_interfaces_testcase.cpp - -namespace Catch { -ITestInvoker::~ITestInvoker() = default; -ITestCaseRegistry::~ITestCaseRegistry() = default; -} -// end catch_interfaces_testcase.cpp -// start catch_leak_detector.cpp - -#ifdef CATCH_CONFIG_WINDOWS_CRTDBG -#include - -namespace Catch { - -LeakDetector::LeakDetector() -{ - int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - flag |= _CRTDBG_LEAK_CHECK_DF; - flag |= _CRTDBG_ALLOC_MEM_DF; - _CrtSetDbgFlag(flag); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - // Change this to leaking allocation's number to break there - _CrtSetBreakAlloc(-1); -} -} - -#else - -Catch::LeakDetector::LeakDetector() { } - -#endif - -Catch::LeakDetector::~LeakDetector() { Catch::cleanUp(); } -// end catch_leak_detector.cpp -// start catch_list.cpp - -// start catch_list.h - -#include - -namespace Catch { - -std::size_t listTests(Config const &config); - -std::size_t listTestsNamesOnly(Config const &config); - -struct TagInfo { - void add(std::string const &spelling); - std::string all() const; - - std::set spellings; - std::size_t count = 0; -}; - -std::size_t listTags(Config const &config); - -std::size_t listReporters(); - -Option list(std::shared_ptr const &config); - -} // end namespace Catch - -// end catch_list.h -// start catch_text.h - -namespace Catch { -using namespace clara::TextFlow; -} - -// end catch_text.h -#include -#include -#include - -namespace Catch { - -std::size_t listTests(Config const &config) -{ - TestSpec const &testSpec = config.testSpec(); - if (config.hasTestFilters()) - Catch::cout() << "Matching test cases:\n"; - else { - Catch::cout() << "All available test cases:\n"; - } - - auto matchedTestCases = - filterTests(getAllTestCasesSorted(config), testSpec, config); - for (auto const &testCaseInfo : matchedTestCases) { - Colour::Code colour = - testCaseInfo.isHidden() ? Colour::SecondaryText : Colour::None; - Colour colourGuard(colour); - - Catch::cout() << Column(testCaseInfo.name).initialIndent(2).indent(4) - << "\n"; - if (config.verbosity() >= Verbosity::High) { - Catch::cout() << Column(Catch::Detail::stringify( - testCaseInfo.lineInfo)) - .indent(4) - << std::endl; - std::string description = testCaseInfo.description; - if (description.empty()) - description = "(NO DESCRIPTION)"; - Catch::cout() << Column(description).indent(4) << std::endl; - } - if (!testCaseInfo.tags.empty()) - Catch::cout() << Column(testCaseInfo.tagsAsString()).indent(6) - << "\n"; - } - - if (!config.hasTestFilters()) - Catch::cout() << pluralise(matchedTestCases.size(), "test case") << '\n' - << std::endl; - else - Catch::cout() << pluralise( - matchedTestCases.size(), "matching test case") - << '\n' - << std::endl; - return matchedTestCases.size(); -} - -std::size_t listTestsNamesOnly(Config const &config) -{ - TestSpec const &testSpec = config.testSpec(); - std::size_t matchedTests = 0; - std::vector matchedTestCases = - filterTests(getAllTestCasesSorted(config), testSpec, config); - for (auto const &testCaseInfo : matchedTestCases) { - matchedTests++; - if (startsWith(testCaseInfo.name, '#')) - Catch::cout() << '"' << testCaseInfo.name << '"'; - else - Catch::cout() << testCaseInfo.name; - if (config.verbosity() >= Verbosity::High) - Catch::cout() << "\t@" << testCaseInfo.lineInfo; - Catch::cout() << std::endl; - } - return matchedTests; -} - -void TagInfo::add(std::string const &spelling) -{ - ++count; - spellings.insert(spelling); -} - -std::string TagInfo::all() const -{ - size_t size = 0; - for (auto const &spelling : spellings) { - // Add 2 for the brackes - size += spelling.size() + 2; - } - - std::string out; - out.reserve(size); - for (auto const &spelling : spellings) { - out += '['; - out += spelling; - out += ']'; - } - return out; -} - -std::size_t listTags(Config const &config) -{ - TestSpec const &testSpec = config.testSpec(); - if (config.hasTestFilters()) - Catch::cout() << "Tags for matching test cases:\n"; - else { - Catch::cout() << "All available tags:\n"; - } - - std::map tagCounts; - - std::vector matchedTestCases = - filterTests(getAllTestCasesSorted(config), testSpec, config); - for (auto const &testCase : matchedTestCases) { - for (auto const &tagName : testCase.getTestCaseInfo().tags) { - std::string lcaseTagName = toLower(tagName); - auto countIt = tagCounts.find(lcaseTagName); - if (countIt == tagCounts.end()) - countIt = - tagCounts.insert(std::make_pair(lcaseTagName, TagInfo())) - .first; - countIt->second.add(tagName); - } - } - - for (auto const &tagCount : tagCounts) { - ReusableStringStream rss; - rss << " " << std::setw(2) << tagCount.second.count << " "; - auto str = rss.str(); - auto wrapper = Column(tagCount.second.all()) - .initialIndent(0) - .indent(str.size()) - .width(CATCH_CONFIG_CONSOLE_WIDTH - 10); - Catch::cout() << str << wrapper << '\n'; - } - Catch::cout() << pluralise(tagCounts.size(), "tag") << '\n' << std::endl; - return tagCounts.size(); -} - -std::size_t listReporters() -{ - Catch::cout() << "Available reporters:\n"; - IReporterRegistry::FactoryMap const &factories = - getRegistryHub().getReporterRegistry().getFactories(); - std::size_t maxNameLen = 0; - for (auto const &factoryKvp : factories) - maxNameLen = (std::max)(maxNameLen, factoryKvp.first.size()); - - for (auto const &factoryKvp : factories) { - Catch::cout() - << Column(factoryKvp.first + ":").indent(2).width(5 + maxNameLen) + - Column(factoryKvp.second->getDescription()) - .initialIndent(0) - .indent(2) - .width(CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8) - << "\n"; - } - Catch::cout() << std::endl; - return factories.size(); -} - -Option list(std::shared_ptr const &config) -{ - Option listedCount; - getCurrentMutableContext().setConfig(config); - if (config->listTests()) - listedCount = listedCount.valueOr(0) + listTests(*config); - if (config->listTestNamesOnly()) - listedCount = listedCount.valueOr(0) + listTestsNamesOnly(*config); - if (config->listTags()) - listedCount = listedCount.valueOr(0) + listTags(*config); - if (config->listReporters()) - listedCount = listedCount.valueOr(0) + listReporters(); - return listedCount; -} - -} // end namespace Catch -// end catch_list.cpp -// start catch_matchers.cpp - -namespace Catch { -namespace Matchers { -namespace Impl { - -std::string MatcherUntypedBase::toString() const -{ - if (m_cachedToString.empty()) - m_cachedToString = describe(); - return m_cachedToString; -} - -MatcherUntypedBase::~MatcherUntypedBase() = default; - -} // namespace Impl -} // namespace Matchers - -using namespace Matchers; -using Matchers::Impl::MatcherBase; - -} // namespace Catch -// end catch_matchers.cpp -// start catch_matchers_exception.cpp - -namespace Catch { -namespace Matchers { -namespace Exception { - -bool ExceptionMessageMatcher::match(std::exception const &ex) const -{ - return ex.what() == m_message; -} - -std::string ExceptionMessageMatcher::describe() const -{ - return "exception message matches \"" + m_message + "\""; -} - -} -Exception::ExceptionMessageMatcher Message(std::string const &message) -{ - return Exception::ExceptionMessageMatcher(message); -} - -// namespace Exception -} // namespace Matchers -} // namespace Catch -// end catch_matchers_exception.cpp -// start catch_matchers_floating.cpp - -// start catch_polyfills.hpp - -namespace Catch { -bool isnan(float f); -bool isnan(double d); -} - -// end catch_polyfills.hpp -// start catch_to_string.hpp - -#include - -namespace Catch { -template std::string to_string(T const &t) -{ -#if defined(CATCH_CONFIG_CPP11_TO_STRING) - return std::to_string(t); -#else - ReusableStringStream rss; - rss << t; - return rss.str(); -#endif -} -} // end namespace Catch - -// end catch_to_string.hpp -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Catch { -namespace { - -int32_t convert(float f) -{ - static_assert(sizeof(float) == sizeof(int32_t), - "Important ULP matcher assumption violated"); - int32_t i; - std::memcpy(&i, &f, sizeof(f)); - return i; -} - -int64_t convert(double d) -{ - static_assert(sizeof(double) == sizeof(int64_t), - "Important ULP matcher assumption violated"); - int64_t i; - std::memcpy(&i, &d, sizeof(d)); - return i; -} - -template bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) -{ - // Comparison with NaN should always be false. - // This way we can rule it out before getting into the ugly details - if (Catch::isnan(lhs) || Catch::isnan(rhs)) { - return false; - } - - auto lc = convert(lhs); - auto rc = convert(rhs); - - if ((lc < 0) != (rc < 0)) { - // Potentially we can have +0 and -0 - return lhs == rhs; - } - - // static cast as a workaround for IBM XLC - auto ulpDiff = std::abs(static_cast(lc - rc)); - return static_cast(ulpDiff) <= maxUlpDiff; -} - -#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) - -float nextafter(float x, float y) { return ::nextafterf(x, y); } - -double nextafter(double x, double y) { return ::nextafter(x, y); } - -#endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^ - -template FP step(FP start, FP direction, uint64_t steps) -{ - for (uint64_t i = 0; i < steps; ++i) { -#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) - start = Catch::nextafter(start, direction); -#else - start = std::nextafter(start, direction); -#endif - } - return start; -} - -// Performs equivalent check of std::fabs(lhs - rhs) <= margin -// But without the subtraction to allow for INFINITY in comparison -bool marginComparison(double lhs, double rhs, double margin) -{ - return (lhs + margin >= rhs) && (rhs + margin >= lhs); -} - -template -void write(std::ostream &out, FloatingPoint num) -{ - out << std::scientific - << std::setprecision( - std::numeric_limits::max_digits10 - 1) - << num; -} - -} // end anonymous namespace - -namespace Matchers { -namespace Floating { - -enum class FloatingPointKind : uint8_t { Float, Double }; - -WithinAbsMatcher::WithinAbsMatcher(double target, double margin) - : m_target{target} - , m_margin{margin} -{ - CATCH_ENFORCE(margin >= 0, - "Invalid margin: " << margin << '.' - << " Margin has to be non-negative."); -} - -// Performs equivalent check of std::fabs(lhs - rhs) <= margin -// But without the subtraction to allow for INFINITY in comparison -bool WithinAbsMatcher::match(double const &matchee) const -{ - return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee); -} - -std::string WithinAbsMatcher::describe() const -{ - return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + - ::Catch::Detail::stringify(m_target); -} - -WithinUlpsMatcher::WithinUlpsMatcher( - double target, uint64_t ulps, FloatingPointKind baseType) - : m_target{target} - , m_ulps{ulps} - , m_type{baseType} -{ - CATCH_ENFORCE(m_type == FloatingPointKind::Double || - m_ulps < (std::numeric_limits::max)(), - "Provided ULP is impossibly large for a float comparison."); -} - -#if defined(__clang__) -#pragma clang diagnostic push -// Clang <3.5 reports on the default branch in the switch below -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - -bool WithinUlpsMatcher::match(double const &matchee) const -{ - switch (m_type) { - case FloatingPointKind::Float: - return almostEqualUlps( - static_cast(matchee), static_cast(m_target), m_ulps); - case FloatingPointKind::Double: - return almostEqualUlps(matchee, m_target, m_ulps); - default: - CATCH_INTERNAL_ERROR("Unknown FloatingPointKind value"); - } -} - -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - -std::string WithinUlpsMatcher::describe() const -{ - std::stringstream ret; - - ret << "is within " << m_ulps << " ULPs of "; - - if (m_type == FloatingPointKind::Float) { - write(ret, static_cast(m_target)); - ret << 'f'; - } - else { - write(ret, m_target); - } - - ret << " (["; - if (m_type == FloatingPointKind::Double) { - write(ret, step(m_target, static_cast(-INFINITY), m_ulps)); - ret << ", "; - write(ret, step(m_target, static_cast(INFINITY), m_ulps)); - } - else { - // We have to cast INFINITY to float because of MinGW, see #1782 - write(ret, - step(static_cast(m_target), static_cast(-INFINITY), - m_ulps)); - ret << ", "; - write(ret, - step(static_cast(m_target), static_cast(INFINITY), - m_ulps)); - } - ret << "])"; - - return ret.str(); -} - -WithinRelMatcher::WithinRelMatcher(double target, double epsilon) - : m_target(target) - , m_epsilon(epsilon) -{ - CATCH_ENFORCE(m_epsilon >= 0., - "Relative comparison with epsilon < 0 does not make sense."); - CATCH_ENFORCE(m_epsilon < 1., - "Relative comparison with epsilon >= 1 does not make sense."); -} - -bool WithinRelMatcher::match(double const &matchee) const -{ - const auto relMargin = - m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target)); - return marginComparison( - matchee, m_target, std::isinf(relMargin) ? 0 : relMargin); -} - -std::string WithinRelMatcher::describe() const -{ - Catch::ReusableStringStream sstr; - sstr << "and " << m_target << " are within " << m_epsilon * 100. - << "% of each other"; - return sstr.str(); -} - -} // namespace Floating - -Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) -{ - return Floating::WithinUlpsMatcher( - target, maxUlpDiff, Floating::FloatingPointKind::Double); -} - -Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) -{ - return Floating::WithinUlpsMatcher( - target, maxUlpDiff, Floating::FloatingPointKind::Float); -} - -Floating::WithinAbsMatcher WithinAbs(double target, double margin) -{ - return Floating::WithinAbsMatcher(target, margin); -} - -Floating::WithinRelMatcher WithinRel(double target, double eps) -{ - return Floating::WithinRelMatcher(target, eps); -} - -Floating::WithinRelMatcher WithinRel(double target) -{ - return Floating::WithinRelMatcher( - target, std::numeric_limits::epsilon() * 100); -} - -Floating::WithinRelMatcher WithinRel(float target, float eps) -{ - return Floating::WithinRelMatcher(target, eps); -} - -Floating::WithinRelMatcher WithinRel(float target) -{ - return Floating::WithinRelMatcher( - target, std::numeric_limits::epsilon() * 100); -} - -} // namespace Matchers -} // namespace Catch -// end catch_matchers_floating.cpp -// start catch_matchers_generic.cpp - -std::string Catch::Matchers::Generic::Detail::finalizeDescription( - const std::string &desc) -{ - if (desc.empty()) { - return "matches undescribed predicate"; - } - else { - return "matches predicate: \"" + desc + '"'; - } -} -// end catch_matchers_generic.cpp -// start catch_matchers_string.cpp - -#include - -namespace Catch { -namespace Matchers { - -namespace StdString { - -CasedString::CasedString( - std::string const &str, CaseSensitive::Choice caseSensitivity) - : m_caseSensitivity(caseSensitivity) - , m_str(adjustString(str)) -{ -} -std::string CasedString::adjustString(std::string const &str) const -{ - return m_caseSensitivity == CaseSensitive::No ? toLower(str) : str; -} -std::string CasedString::caseSensitivitySuffix() const -{ - return m_caseSensitivity == CaseSensitive::No ? " (case insensitive)" - : std::string(); -} - -StringMatcherBase::StringMatcherBase( - std::string const &operation, CasedString const &comparator) - : m_comparator(comparator) - , m_operation(operation) -{ -} - -std::string StringMatcherBase::describe() const -{ - std::string description; - description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + - m_comparator.caseSensitivitySuffix().size()); - description += m_operation; - description += ": \""; - description += m_comparator.m_str; - description += "\""; - description += m_comparator.caseSensitivitySuffix(); - return description; -} - -EqualsMatcher::EqualsMatcher(CasedString const &comparator) - : StringMatcherBase("equals", comparator) -{ -} - -bool EqualsMatcher::match(std::string const &source) const -{ - return m_comparator.adjustString(source) == m_comparator.m_str; -} - -ContainsMatcher::ContainsMatcher(CasedString const &comparator) - : StringMatcherBase("contains", comparator) -{ -} - -bool ContainsMatcher::match(std::string const &source) const -{ - return contains(m_comparator.adjustString(source), m_comparator.m_str); -} - -StartsWithMatcher::StartsWithMatcher(CasedString const &comparator) - : StringMatcherBase("starts with", comparator) -{ -} - -bool StartsWithMatcher::match(std::string const &source) const -{ - return startsWith(m_comparator.adjustString(source), m_comparator.m_str); -} - -EndsWithMatcher::EndsWithMatcher(CasedString const &comparator) - : StringMatcherBase("ends with", comparator) -{ -} - -bool EndsWithMatcher::match(std::string const &source) const -{ - return endsWith(m_comparator.adjustString(source), m_comparator.m_str); -} - -RegexMatcher::RegexMatcher( - std::string regex, CaseSensitive::Choice caseSensitivity) - : m_regex(std::move(regex)) - , m_caseSensitivity(caseSensitivity) -{ -} - -bool RegexMatcher::match(std::string const &matchee) const -{ - auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax - // option anyway - - if (m_caseSensitivity == CaseSensitive::Choice::No) { - flags |= std::regex::icase; - } - auto reg = std::regex(m_regex, flags); - return std::regex_search(matchee, reg); -} - -std::string RegexMatcher::describe() const -{ - return "matches " + ::Catch::Detail::stringify(m_regex) + - ((m_caseSensitivity == CaseSensitive::Choice::Yes) - ? " case sensitively" - : " case insensitively"); -} - -} // namespace StdString - -StdString::EqualsMatcher Equals( - std::string const &str, CaseSensitive::Choice caseSensitivity) -{ - return StdString::EqualsMatcher( - StdString::CasedString(str, caseSensitivity)); -} -StdString::ContainsMatcher Contains( - std::string const &str, CaseSensitive::Choice caseSensitivity) -{ - return StdString::ContainsMatcher( - StdString::CasedString(str, caseSensitivity)); -} -StdString::EndsWithMatcher EndsWith( - std::string const &str, CaseSensitive::Choice caseSensitivity) -{ - return StdString::EndsWithMatcher( - StdString::CasedString(str, caseSensitivity)); -} -StdString::StartsWithMatcher StartsWith( - std::string const &str, CaseSensitive::Choice caseSensitivity) -{ - return StdString::StartsWithMatcher( - StdString::CasedString(str, caseSensitivity)); -} - -StdString::RegexMatcher Matches( - std::string const ®ex, CaseSensitive::Choice caseSensitivity) -{ - return StdString::RegexMatcher(regex, caseSensitivity); -} - -} // namespace Matchers -} // namespace Catch -// end catch_matchers_string.cpp -// start catch_message.cpp - -// start catch_uncaught_exceptions.h - -namespace Catch { -bool uncaught_exceptions(); -} // end namespace Catch - -// end catch_uncaught_exceptions.h -#include -#include - -namespace Catch { - -MessageInfo::MessageInfo(StringRef const &_macroName, - SourceLineInfo const &_lineInfo, ResultWas::OfType _type) - : macroName(_macroName) - , lineInfo(_lineInfo) - , type(_type) - , sequence(++globalCount) -{ -} - -bool MessageInfo::operator==(MessageInfo const &other) const -{ - return sequence == other.sequence; -} - -bool MessageInfo::operator<(MessageInfo const &other) const -{ - return sequence < other.sequence; -} - -// This may need protecting if threading support is added -unsigned int MessageInfo::globalCount = 0; - -//////////////////////////////////////////////////////////////////////////// - -Catch::MessageBuilder::MessageBuilder(StringRef const ¯oName, - SourceLineInfo const &lineInfo, ResultWas::OfType type) - : m_info(macroName, lineInfo, type) -{ -} - -//////////////////////////////////////////////////////////////////////////// - -ScopedMessage::ScopedMessage(MessageBuilder const &builder) - : m_info(builder.m_info) - , m_moved() -{ - m_info.message = builder.m_stream.str(); - getResultCapture().pushScopedMessage(m_info); -} - -ScopedMessage::ScopedMessage(ScopedMessage &&old) - : m_info(old.m_info) - , m_moved() -{ - old.m_moved = true; -} - -ScopedMessage::~ScopedMessage() -{ - if (!uncaught_exceptions() && !m_moved) { - getResultCapture().popScopedMessage(m_info); - } -} - -Capturer::Capturer(StringRef macroName, SourceLineInfo const &lineInfo, - ResultWas::OfType resultType, StringRef names) -{ - auto trimmed = [&](size_t start, size_t end) { - while (names[start] == ',' || - isspace(static_cast(names[start]))) { - ++start; - } - while (names[end] == ',' || - isspace(static_cast(names[end]))) { - --end; - } - return names.substr(start, end - start + 1); - }; - auto skipq = [&](size_t start, char quote) { - for (auto i = start + 1; i < names.size(); ++i) { - if (names[i] == quote) - return i; - if (names[i] == '\\') - ++i; - } - CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote"); - }; - - size_t start = 0; - std::stack openings; - for (size_t pos = 0; pos < names.size(); ++pos) { - char c = names[pos]; - switch (c) { - case '[': - case '{': - case '(': - // It is basically impossible to disambiguate between - // comparison and start of template args in this context - // case '<': - openings.push(c); - break; - case ']': - case '}': - case ')': - // case '>': - openings.pop(); - break; - case '"': - case '\'': - pos = skipq(pos, c); - break; - case ',': - if (start != pos && openings.empty()) { - m_messages.emplace_back(macroName, lineInfo, resultType); - m_messages.back().message = - static_cast(trimmed(start, pos)); - m_messages.back().message += " := "; - start = pos; - } - } - } - assert(openings.empty() && "Mismatched openings"); - m_messages.emplace_back(macroName, lineInfo, resultType); - m_messages.back().message = - static_cast(trimmed(start, names.size() - 1)); - m_messages.back().message += " := "; -} -Capturer::~Capturer() -{ - if (!uncaught_exceptions()) { - assert(m_captured == m_messages.size()); - for (size_t i = 0; i < m_captured; ++i) - m_resultCapture.popScopedMessage(m_messages[i]); - } -} - -void Capturer::captureValue(size_t index, std::string const &value) -{ - assert(index < m_messages.size()); - m_messages[index].message += value; - m_resultCapture.pushScopedMessage(m_messages[index]); - m_captured++; -} - -} // end namespace Catch -// end catch_message.cpp -// start catch_output_redirect.cpp - -// start catch_output_redirect.h -#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H -#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H - -#include -#include -#include - -namespace Catch { - -class RedirectedStream { - std::ostream &m_originalStream; - std::ostream &m_redirectionStream; - std::streambuf *m_prevBuf; - -public: - RedirectedStream( - std::ostream &originalStream, std::ostream &redirectionStream); - ~RedirectedStream(); -}; - -class RedirectedStdOut { - ReusableStringStream m_rss; - RedirectedStream m_cout; - -public: - RedirectedStdOut(); - auto str() const -> std::string; -}; - -// StdErr has two constituent streams in C++, std::cerr and std::clog -// This means that we need to redirect 2 streams into 1 to keep proper -// order of writes -class RedirectedStdErr { - ReusableStringStream m_rss; - RedirectedStream m_cerr; - RedirectedStream m_clog; - -public: - RedirectedStdErr(); - auto str() const -> std::string; -}; - -class RedirectedStreams { -public: - RedirectedStreams(RedirectedStreams const &) = delete; - RedirectedStreams &operator=(RedirectedStreams const &) = delete; - RedirectedStreams(RedirectedStreams &&) = delete; - RedirectedStreams &operator=(RedirectedStreams &&) = delete; - - RedirectedStreams(std::string &redirectedCout, std::string &redirectedCerr); - ~RedirectedStreams(); - -private: - std::string &m_redirectedCout; - std::string &m_redirectedCerr; - RedirectedStdOut m_redirectedStdOut; - RedirectedStdErr m_redirectedStdErr; -}; - -#if defined(CATCH_CONFIG_NEW_CAPTURE) - -// Windows's implementation of std::tmpfile is terrible (it tries -// to create a file inside system folder, thus requiring elevated -// privileges for the binary), so we have to use tmpnam(_s) and -// create the file ourselves there. -class TempFile { -public: - TempFile(TempFile const &) = delete; - TempFile &operator=(TempFile const &) = delete; - TempFile(TempFile &&) = delete; - TempFile &operator=(TempFile &&) = delete; - - TempFile(); - ~TempFile(); - - std::FILE *getFile(); - std::string getContents(); - -private: - std::FILE *m_file = nullptr; -#if defined(_MSC_VER) - char m_buffer[L_tmpnam] = {0}; -#endif -}; - -class OutputRedirect { -public: - OutputRedirect(OutputRedirect const &) = delete; - OutputRedirect &operator=(OutputRedirect const &) = delete; - OutputRedirect(OutputRedirect &&) = delete; - OutputRedirect &operator=(OutputRedirect &&) = delete; - - OutputRedirect(std::string &stdout_dest, std::string &stderr_dest); - ~OutputRedirect(); - -private: - int m_originalStdout = -1; - int m_originalStderr = -1; - TempFile m_stdoutFile; - TempFile m_stderrFile; - std::string &m_stdoutDest; - std::string &m_stderrDest; -}; - -#endif - -} // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H -// end catch_output_redirect.h -#include -#include -#include -#include -#include - -#if defined(CATCH_CONFIG_NEW_CAPTURE) -#if defined(_MSC_VER) -#include //_dup and _dup2 -#define dup _dup -#define dup2 _dup2 -#define fileno _fileno -#else -#include // dup and dup2 -#endif -#endif - -namespace Catch { - -RedirectedStream::RedirectedStream( - std::ostream &originalStream, std::ostream &redirectionStream) - : m_originalStream(originalStream) - , m_redirectionStream(redirectionStream) - , m_prevBuf(m_originalStream.rdbuf()) -{ - m_originalStream.rdbuf(m_redirectionStream.rdbuf()); -} - -RedirectedStream::~RedirectedStream() { m_originalStream.rdbuf(m_prevBuf); } - -RedirectedStdOut::RedirectedStdOut() - : m_cout(Catch::cout(), m_rss.get()) -{ -} -auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); } - -RedirectedStdErr::RedirectedStdErr() - : m_cerr(Catch::cerr(), m_rss.get()) - , m_clog(Catch::clog(), m_rss.get()) -{ -} -auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } - -RedirectedStreams::RedirectedStreams( - std::string &redirectedCout, std::string &redirectedCerr) - : m_redirectedCout(redirectedCout) - , m_redirectedCerr(redirectedCerr) -{ -} - -RedirectedStreams::~RedirectedStreams() -{ - m_redirectedCout += m_redirectedStdOut.str(); - m_redirectedCerr += m_redirectedStdErr.str(); -} - -#if defined(CATCH_CONFIG_NEW_CAPTURE) - -#if defined(_MSC_VER) -TempFile::TempFile() -{ - if (tmpnam_s(m_buffer)) { - CATCH_RUNTIME_ERROR("Could not get a temp filename"); - } - if (fopen_s(&m_file, m_buffer, "w+")) { - char buffer[100]; - if (strerror_s(buffer, errno)) { - CATCH_RUNTIME_ERROR("Could not translate errno to a string"); - } - CATCH_RUNTIME_ERROR("Could not open the temp file: '" - << m_buffer << "' because: " << buffer); - } -} -#else -TempFile::TempFile() -{ - m_file = std::tmpfile(); - if (!m_file) { - CATCH_RUNTIME_ERROR("Could not create a temp file."); - } -} - -#endif - -TempFile::~TempFile() -{ - // TBD: What to do about errors here? - std::fclose(m_file); - // We manually create the file on Windows only, on Linux - // it will be autodeleted -#if defined(_MSC_VER) - std::remove(m_buffer); -#endif -} - -FILE *TempFile::getFile() { return m_file; } - -std::string TempFile::getContents() -{ - std::stringstream sstr; - char buffer[100] = {}; - std::rewind(m_file); - while (std::fgets(buffer, sizeof(buffer), m_file)) { - sstr << buffer; - } - return sstr.str(); -} - -OutputRedirect::OutputRedirect( - std::string &stdout_dest, std::string &stderr_dest) - : m_originalStdout(dup(1)) - , m_originalStderr(dup(2)) - , m_stdoutDest(stdout_dest) - , m_stderrDest(stderr_dest) -{ - dup2(fileno(m_stdoutFile.getFile()), 1); - dup2(fileno(m_stderrFile.getFile()), 2); -} - -OutputRedirect::~OutputRedirect() -{ - Catch::cout() << std::flush; - fflush(stdout); - // Since we support overriding these streams, we flush cerr - // even though std::cerr is unbuffered - Catch::cerr() << std::flush; - Catch::clog() << std::flush; - fflush(stderr); - - dup2(m_originalStdout, 1); - dup2(m_originalStderr, 2); - - m_stdoutDest += m_stdoutFile.getContents(); - m_stderrDest += m_stderrFile.getContents(); -} - -#endif // CATCH_CONFIG_NEW_CAPTURE - -} // namespace Catch - -#if defined(CATCH_CONFIG_NEW_CAPTURE) -#if defined(_MSC_VER) -#undef dup -#undef dup2 -#undef fileno -#endif -#endif -// end catch_output_redirect.cpp -// start catch_polyfills.cpp - -#include - -namespace Catch { - -#if !defined(CATCH_CONFIG_POLYFILL_ISNAN) -bool isnan(float f) { return std::isnan(f); } -bool isnan(double d) { return std::isnan(d); } -#else -// For now we only use this for embarcadero -bool isnan(float f) { return std::_isnan(f); } -bool isnan(double d) { return std::_isnan(d); } -#endif - -} // end namespace Catch -// end catch_polyfills.cpp -// start catch_random_number_generator.cpp - -namespace Catch { - -namespace { - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4146) // we negate uint32 during the rotate -#endif -// Safe rotr implementation thanks to John Regehr -uint32_t rotate_right(uint32_t val, uint32_t count) -{ - const uint32_t mask = 31; - count &= mask; - return (val >> count) | (val << (-count & mask)); -} - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -} - -SimplePcg32::SimplePcg32(result_type seed_) { seed(seed_); } - -void SimplePcg32::seed(result_type seed_) -{ - m_state = 0; - (*this)(); - m_state += seed_; - (*this)(); -} - -void SimplePcg32::discard(uint64_t skip) -{ - // We could implement this to run in O(log n) steps, but this - // should suffice for our use case. - for (uint64_t s = 0; s < skip; ++s) { - static_cast((*this)()); - } -} - -SimplePcg32::result_type SimplePcg32::operator()() -{ - // prepare the output value - const uint32_t xorshifted = - static_cast(((m_state >> 18u) ^ m_state) >> 27u); - const auto output = rotate_right(xorshifted, m_state >> 59u); - - // advance state - m_state = m_state * 6364136223846793005ULL + s_inc; - - return output; -} - -bool operator==(SimplePcg32 const &lhs, SimplePcg32 const &rhs) -{ - return lhs.m_state == rhs.m_state; -} - -bool operator!=(SimplePcg32 const &lhs, SimplePcg32 const &rhs) -{ - return lhs.m_state != rhs.m_state; -} -} -// end catch_random_number_generator.cpp -// start catch_registry_hub.cpp - -// start catch_test_case_registry_impl.h - -#include -#include -#include -#include - -namespace Catch { - -class TestCase; -struct IConfig; - -std::vector sortTests( - IConfig const &config, std::vector const &unsortedTestCases); - -bool isThrowSafe(TestCase const &testCase, IConfig const &config); -bool matchTest( - TestCase const &testCase, TestSpec const &testSpec, IConfig const &config); - -void enforceNoDuplicateTestCases(std::vector const &functions); - -std::vector filterTests(std::vector const &testCases, - TestSpec const &testSpec, IConfig const &config); -std::vector const &getAllTestCasesSorted(IConfig const &config); - -class TestRegistry : public ITestCaseRegistry { -public: - virtual ~TestRegistry() = default; - - virtual void registerTest(TestCase const &testCase); - - std::vector const &getAllTests() const override; - std::vector const &getAllTestsSorted( - IConfig const &config) const override; - -private: - std::vector m_functions; - mutable RunTests::InWhatOrder m_currentSortOrder = - RunTests::InDeclarationOrder; - mutable std::vector m_sortedFunctions; - std::size_t m_unnamedCount = 0; - std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised -}; - -/////////////////////////////////////////////////////////////////////////// - -class TestInvokerAsFunction : public ITestInvoker { - void (*m_testAsFunction)(); - -public: - TestInvokerAsFunction(void (*testAsFunction)()) noexcept; - - void invoke() const override; -}; - -std::string extractClassName(StringRef const &classOrQualifiedMethodName); - -/////////////////////////////////////////////////////////////////////////// - -} // end namespace Catch - -// end catch_test_case_registry_impl.h -// start catch_reporter_registry.h - -#include - -namespace Catch { - -class ReporterRegistry : public IReporterRegistry { - -public: - ~ReporterRegistry() override; - - IStreamingReporterPtr create( - std::string const &name, IConfigPtr const &config) const override; - - void registerReporter( - std::string const &name, IReporterFactoryPtr const &factory); - void registerListener(IReporterFactoryPtr const &factory); - - FactoryMap const &getFactories() const override; - Listeners const &getListeners() const override; - -private: - FactoryMap m_factories; - Listeners m_listeners; -}; -} - -// end catch_reporter_registry.h -// start catch_tag_alias_registry.h - -// start catch_tag_alias.h - -#include - -namespace Catch { - -struct TagAlias { - TagAlias(std::string const &_tag, SourceLineInfo _lineInfo); - - std::string tag; - SourceLineInfo lineInfo; -}; - -} // end namespace Catch - -// end catch_tag_alias.h -#include - -namespace Catch { - -class TagAliasRegistry : public ITagAliasRegistry { -public: - ~TagAliasRegistry() override; - TagAlias const *find(std::string const &alias) const override; - std::string expandAliases( - std::string const &unexpandedTestSpec) const override; - void add(std::string const &alias, std::string const &tag, - SourceLineInfo const &lineInfo); - -private: - std::map m_registry; -}; - -} // end namespace Catch - -// end catch_tag_alias_registry.h -// start catch_startup_exception_registry.h - -#include -#include - -namespace Catch { - -class StartupExceptionRegistry { -#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -public: - void add(std::exception_ptr const &exception) noexcept; - std::vector const &getExceptions() const noexcept; - -private: - std::vector m_exceptions; -#endif -}; - -} // end namespace Catch - -// end catch_startup_exception_registry.h -// start catch_singletons.hpp - -namespace Catch { - -struct ISingleton { - virtual ~ISingleton(); -}; - -void addSingleton(ISingleton *singleton); -void cleanupSingletons(); - -template -class Singleton : SingletonImplT, public ISingleton { - - static auto getInternal() -> Singleton * - { - static Singleton *s_instance = nullptr; - if (!s_instance) { - s_instance = new Singleton; - addSingleton(s_instance); - } - return s_instance; - } - -public: - static auto get() -> InterfaceT const & { return *getInternal(); } - static auto getMutable() -> MutableInterfaceT & { return *getInternal(); } -}; - -} // namespace Catch - -// end catch_singletons.hpp -namespace Catch { - -namespace { - -class RegistryHub : public IRegistryHub, - public IMutableRegistryHub, - private NonCopyable { - -public: // IRegistryHub - RegistryHub() = default; - IReporterRegistry const &getReporterRegistry() const override - { - return m_reporterRegistry; - } - ITestCaseRegistry const &getTestCaseRegistry() const override - { - return m_testCaseRegistry; - } - IExceptionTranslatorRegistry const & - getExceptionTranslatorRegistry() const override - { - return m_exceptionTranslatorRegistry; - } - ITagAliasRegistry const &getTagAliasRegistry() const override - { - return m_tagAliasRegistry; - } - StartupExceptionRegistry const &getStartupExceptionRegistry() const override - { - return m_exceptionRegistry; - } - -public: // IMutableRegistryHub - void registerReporter( - std::string const &name, IReporterFactoryPtr const &factory) override - { - m_reporterRegistry.registerReporter(name, factory); - } - void registerListener(IReporterFactoryPtr const &factory) override - { - m_reporterRegistry.registerListener(factory); - } - void registerTest(TestCase const &testInfo) override - { - m_testCaseRegistry.registerTest(testInfo); - } - void registerTranslator(const IExceptionTranslator *translator) override - { - m_exceptionTranslatorRegistry.registerTranslator(translator); - } - void registerTagAlias(std::string const &alias, std::string const &tag, - SourceLineInfo const &lineInfo) override - { - m_tagAliasRegistry.add(alias, tag, lineInfo); - } - void registerStartupException() noexcept override - { -#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - m_exceptionRegistry.add(std::current_exception()); -#else - CATCH_INTERNAL_ERROR("Attempted to register active exception under " - "CATCH_CONFIG_DISABLE_EXCEPTIONS!"); -#endif - } - IMutableEnumValuesRegistry &getMutableEnumValuesRegistry() override - { - return m_enumValuesRegistry; - } - -private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; - TagAliasRegistry m_tagAliasRegistry; - StartupExceptionRegistry m_exceptionRegistry; - Detail::EnumValuesRegistry m_enumValuesRegistry; -}; -} - -using RegistryHubSingleton = - Singleton; - -IRegistryHub const &getRegistryHub() { return RegistryHubSingleton::get(); } -IMutableRegistryHub &getMutableRegistryHub() -{ - return RegistryHubSingleton::getMutable(); -} -void cleanUp() -{ - cleanupSingletons(); - cleanUpContext(); -} -std::string translateActiveException() -{ - return getRegistryHub() - .getExceptionTranslatorRegistry() - .translateActiveException(); -} - -} // end namespace Catch -// end catch_registry_hub.cpp -// start catch_reporter_registry.cpp - -namespace Catch { - -ReporterRegistry::~ReporterRegistry() = default; - -IStreamingReporterPtr ReporterRegistry::create( - std::string const &name, IConfigPtr const &config) const -{ - auto it = m_factories.find(name); - if (it == m_factories.end()) - return nullptr; - return it->second->create(ReporterConfig(config)); -} - -void ReporterRegistry::registerReporter( - std::string const &name, IReporterFactoryPtr const &factory) -{ - m_factories.emplace(name, factory); -} -void ReporterRegistry::registerListener(IReporterFactoryPtr const &factory) -{ - m_listeners.push_back(factory); -} - -IReporterRegistry::FactoryMap const &ReporterRegistry::getFactories() const -{ - return m_factories; -} -IReporterRegistry::Listeners const &ReporterRegistry::getListeners() const -{ - return m_listeners; -} - -} -// end catch_reporter_registry.cpp -// start catch_result_type.cpp - -namespace Catch { - -bool isOk(ResultWas::OfType resultType) -{ - return (resultType & ResultWas::FailureBit) == 0; -} -bool isJustInfo(int flags) { return flags == ResultWas::Info; } - -ResultDisposition::Flags operator|( - ResultDisposition::Flags lhs, ResultDisposition::Flags rhs) -{ - return static_cast( - static_cast(lhs) | static_cast(rhs)); -} - -bool shouldContinueOnFailure(int flags) -{ - return (flags & ResultDisposition::ContinueOnFailure) != 0; -} -bool shouldSuppressFailure(int flags) -{ - return (flags & ResultDisposition::SuppressFail) != 0; -} - -} // end namespace Catch -// end catch_result_type.cpp -// start catch_run_context.cpp - -#include -#include -#include - -namespace Catch { - -namespace Generators { -struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { - GeneratorBasePtr m_generator; - - GeneratorTracker(TestCaseTracking::NameAndLocation const &nameAndLocation, - TrackerContext &ctx, ITracker *parent) - : TrackerBase(nameAndLocation, ctx, parent) - { - } - ~GeneratorTracker(); - - static GeneratorTracker &acquire(TrackerContext &ctx, - TestCaseTracking::NameAndLocation const &nameAndLocation) - { - std::shared_ptr tracker; - - ITracker ¤tTracker = ctx.currentTracker(); - // Under specific circumstances, the generator we want - // to acquire is also the current tracker. If this is - // the case, we have to avoid looking through current - // tracker's children, and instead return the current - // tracker. - // A case where this check is important is e.g. - // for (int i = 0; i < 5; ++i) { - // int n = GENERATE(1, 2); - // } - // - // without it, the code above creates 5 nested generators. - if (currentTracker.nameAndLocation() == nameAndLocation) { - auto thisTracker = - currentTracker.parent().findChild(nameAndLocation); - assert(thisTracker); - assert(thisTracker->isGeneratorTracker()); - tracker = std::static_pointer_cast(thisTracker); - } - else if (TestCaseTracking::ITrackerPtr childTracker = - currentTracker.findChild(nameAndLocation)) { - assert(childTracker); - assert(childTracker->isGeneratorTracker()); - tracker = std::static_pointer_cast(childTracker); - } - else { - tracker = std::make_shared( - nameAndLocation, ctx, ¤tTracker); - currentTracker.addChild(tracker); - } - - if (!tracker->isComplete()) { - tracker->open(); - } - - return *tracker; - } - - // TrackerBase interface - bool isGeneratorTracker() const override { return true; } - auto hasGenerator() const -> bool override { return !!m_generator; } - void close() override - { - TrackerBase::close(); - // If a generator has a child (it is followed by a section) - // and none of its children have started, then we must wait - // until later to start consuming its values. - // This catches cases where `GENERATE` is placed between two - // `SECTION`s. - // **The check for m_children.empty cannot be removed**. - // doing so would break `GENERATE` _not_ followed by `SECTION`s. - const bool should_wait_for_child = [&]() { - // No children -> nobody to wait for - if (m_children.empty()) { - return false; - } - // If at least one child started executing, don't wait - if (std::find_if(m_children.begin(), m_children.end(), - [](TestCaseTracking::ITrackerPtr tracker) { - return tracker->hasStarted(); - }) != m_children.end()) { - return false; - } - - // No children have started. We need to check if they _can_ - // start, and thus we should wait for them, or they cannot - // start (due to filters), and we shouldn't wait for them - auto *parent = m_parent; - // This is safe: there is always at least one section - // tracker in a test case tracking tree - while (!parent->isSectionTracker()) { - parent = &(parent->parent()); - } - assert(parent && "Missing root (test case) level section"); - - auto const &parentSection = static_cast(*parent); - auto const &filters = parentSection.getFilters(); - // No filters -> no restrictions on running sections - if (filters.empty()) { - return true; - } - - for (auto const &child : m_children) { - if (child->isSectionTracker() && - std::find(filters.begin(), filters.end(), - static_cast(*child).trimmedName()) != - filters.end()) { - return true; - } - } - return false; - }(); - - // This check is a bit tricky, because m_generator->next() - // has a side-effect, where it consumes generator's current - // value, but we do not want to invoke the side-effect if - // this generator is still waiting for any child to start. - if (should_wait_for_child || - (m_runState == CompletedSuccessfully && m_generator->next())) { - m_children.clear(); - m_runState = Executing; - } - } - - // IGeneratorTracker interface - auto getGenerator() const -> GeneratorBasePtr const & override - { - return m_generator; - } - void setGenerator(GeneratorBasePtr &&generator) override - { - m_generator = std::move(generator); - } -}; -GeneratorTracker::~GeneratorTracker() { } -} - -RunContext::RunContext( - IConfigPtr const &_config, IStreamingReporterPtr &&reporter) - : m_runInfo(_config->name()) - , m_context(getCurrentMutableContext()) - , m_config(_config) - , m_reporter(std::move(reporter)) - , m_lastAssertionInfo{StringRef(), SourceLineInfo("", 0), StringRef(), - ResultDisposition::Normal} - , m_includeSuccessfulResults(m_config->includeSuccessfulResults() || - m_reporter->getPreferences().shouldReportAllAssertions) -{ - m_context.setRunner(this); - m_context.setConfig(m_config); - m_context.setResultCapture(this); - m_reporter->testRunStarting(m_runInfo); -} - -RunContext::~RunContext() -{ - m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); -} - -void RunContext::testGroupStarting(std::string const &testSpec, - std::size_t groupIndex, std::size_t groupsCount) -{ - m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); -} - -void RunContext::testGroupEnded(std::string const &testSpec, - Totals const &totals, std::size_t groupIndex, std::size_t groupsCount) -{ - m_reporter->testGroupEnded(TestGroupStats( - GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting())); -} - -Totals RunContext::runTest(TestCase const &testCase) -{ - Totals prevTotals = m_totals; - - std::string redirectedCout; - std::string redirectedCerr; - - auto const &testInfo = testCase.getTestCaseInfo(); - - m_reporter->testCaseStarting(testInfo); - - m_activeTestCase = &testCase; - - ITracker &rootTracker = m_trackerContext.startRun(); - assert(rootTracker.isSectionTracker()); - static_cast(rootTracker) - .addInitialFilters(m_config->getSectionsToRun()); - do { - m_trackerContext.startCycle(); - m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, - TestCaseTracking::NameAndLocation( - testInfo.name, testInfo.lineInfo)); - runCurrentTest(redirectedCout, redirectedCerr); - } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); - - Totals deltaTotals = m_totals.delta(prevTotals); - if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { - deltaTotals.assertions.failed++; - deltaTotals.testCases.passed--; - deltaTotals.testCases.failed++; - } - m_totals.testCases += deltaTotals.testCases; - m_reporter->testCaseEnded(TestCaseStats( - testInfo, deltaTotals, redirectedCout, redirectedCerr, aborting())); - - m_activeTestCase = nullptr; - m_testCaseTracker = nullptr; - - return deltaTotals; -} - -IConfigPtr RunContext::config() const { return m_config; } - -IStreamingReporter &RunContext::reporter() const { return *m_reporter; } - -void RunContext::assertionEnded(AssertionResult const &result) -{ - if (result.getResultType() == ResultWas::Ok) { - m_totals.assertions.passed++; - m_lastAssertionPassed = true; - } - else if (!result.isOk()) { - m_lastAssertionPassed = false; - if (m_activeTestCase->getTestCaseInfo().okToFail()) - m_totals.assertions.failedButOk++; - else - m_totals.assertions.failed++; - } - else { - m_lastAssertionPassed = true; - } - - // We have no use for the return value (whether messages should be cleared), - // because messages were made scoped and should be let to clear themselves - // out. - static_cast(m_reporter->assertionEnded( - AssertionStats(result, m_messages, m_totals))); - - if (result.getResultType() != ResultWas::Warning) - m_messageScopes.clear(); - - // Reset working state - resetAssertionInfo(); - m_lastResult = result; -} -void RunContext::resetAssertionInfo() -{ - m_lastAssertionInfo.macroName = StringRef(); - m_lastAssertionInfo.capturedExpression = - "{Unknown expression after the reported line}"_sr; -} - -bool RunContext::sectionStarted( - SectionInfo const §ionInfo, Counts &assertions) -{ - ITracker §ionTracker = SectionTracker::acquire(m_trackerContext, - TestCaseTracking::NameAndLocation( - sectionInfo.name, sectionInfo.lineInfo)); - if (!sectionTracker.isOpen()) - return false; - m_activeSections.push_back(§ionTracker); - - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - - m_reporter->sectionStarting(sectionInfo); - - assertions = m_totals.assertions; - - return true; -} -auto RunContext::acquireGeneratorTracker(StringRef generatorName, - SourceLineInfo const &lineInfo) -> IGeneratorTracker & -{ - using namespace Generators; - GeneratorTracker &tracker = GeneratorTracker::acquire(m_trackerContext, - TestCaseTracking::NameAndLocation( - static_cast(generatorName), lineInfo)); - m_lastAssertionInfo.lineInfo = lineInfo; - return tracker; -} - -bool RunContext::testForMissingAssertions(Counts &assertions) -{ - if (assertions.total() != 0) - return false; - if (!m_config->warnAboutMissingAssertions()) - return false; - if (m_trackerContext.currentTracker().hasChildren()) - return false; - m_totals.assertions.failed++; - assertions.failed++; - return true; -} - -void RunContext::sectionEnded(SectionEndInfo const &endInfo) -{ - Counts assertions = m_totals.assertions - endInfo.prevAssertions; - bool missingAssertions = testForMissingAssertions(assertions); - - if (!m_activeSections.empty()) { - m_activeSections.back()->close(); - m_activeSections.pop_back(); - } - - m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, - endInfo.durationInSeconds, missingAssertions)); - m_messages.clear(); - m_messageScopes.clear(); -} - -void RunContext::sectionEndedEarly(SectionEndInfo const &endInfo) -{ - if (m_unfinishedSections.empty()) - m_activeSections.back()->fail(); - else - m_activeSections.back()->close(); - m_activeSections.pop_back(); - - m_unfinishedSections.push_back(endInfo); -} - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -void RunContext::benchmarkPreparing(std::string const &name) -{ - m_reporter->benchmarkPreparing(name); -} -void RunContext::benchmarkStarting(BenchmarkInfo const &info) -{ - m_reporter->benchmarkStarting(info); -} -void RunContext::benchmarkEnded(BenchmarkStats<> const &stats) -{ - m_reporter->benchmarkEnded(stats); -} -void RunContext::benchmarkFailed(std::string const &error) -{ - m_reporter->benchmarkFailed(error); -} -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - -void RunContext::pushScopedMessage(MessageInfo const &message) -{ - m_messages.push_back(message); -} - -void RunContext::popScopedMessage(MessageInfo const &message) -{ - m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), - m_messages.end()); -} - -void RunContext::emplaceUnscopedMessage(MessageBuilder const &builder) -{ - m_messageScopes.emplace_back(builder); -} - -std::string RunContext::getCurrentTestName() const -{ - return m_activeTestCase ? m_activeTestCase->getTestCaseInfo().name - : std::string(); -} - -const AssertionResult *RunContext::getLastResult() const -{ - return &(*m_lastResult); -} - -void RunContext::exceptionEarlyReported() { m_shouldReportUnexpected = false; } - -void RunContext::handleFatalErrorCondition(StringRef message) -{ - // First notify reporter that bad things happened - m_reporter->fatalErrorEncountered(message); - - // Don't rebuild the result -- the stringification itself can cause more - // fatal errors Instead, fake a result data. - AssertionResultData tempResult(ResultWas::FatalErrorCondition, {false}); - tempResult.message = static_cast(message); - AssertionResult result(m_lastAssertionInfo, tempResult); - - assertionEnded(result); - - handleUnfinishedSections(); - - // Recreate section for test case (as we will lose the one that was in - // scope) - auto const &testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); - - Counts assertions; - assertions.failed = 1; - SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); - m_reporter->sectionEnded(testCaseSectionStats); - - auto const &testInfo = m_activeTestCase->getTestCaseInfo(); - - Totals deltaTotals; - deltaTotals.testCases.failed = 1; - deltaTotals.assertions.failed = 1; - m_reporter->testCaseEnded(TestCaseStats( - testInfo, deltaTotals, std::string(), std::string(), false)); - m_totals.testCases.failed++; - testGroupEnded(std::string(), m_totals, 1, 1); - m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); -} - -bool RunContext::lastAssertionPassed() { return m_lastAssertionPassed; } - -void RunContext::assertionPassed() -{ - m_lastAssertionPassed = true; - ++m_totals.assertions.passed; - resetAssertionInfo(); - m_messageScopes.clear(); -} - -bool RunContext::aborting() const -{ - return m_totals.assertions.failed >= - static_cast(m_config->abortAfter()); -} - -void RunContext::runCurrentTest( - std::string &redirectedCout, std::string &redirectedCerr) -{ - auto const &testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); - m_reporter->sectionStarting(testCaseSection); - Counts prevAssertions = m_totals.assertions; - double duration = 0; - m_shouldReportUnexpected = true; - m_lastAssertionInfo = {"TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), - ResultDisposition::Normal}; - - seedRng(*m_config); - - Timer timer; - CATCH_TRY - { - if (m_reporter->getPreferences().shouldRedirectStdOut) { -#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) - RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr); - - timer.start(); - invokeActiveTestCase(); -#else - OutputRedirect r(redirectedCout, redirectedCerr); - timer.start(); - invokeActiveTestCase(); -#endif - } - else { - timer.start(); - invokeActiveTestCase(); - } - duration = timer.getElapsedSeconds(); - } - CATCH_CATCH_ANON(TestFailureException &) - { - // This just means the test was aborted due to failure - } - CATCH_CATCH_ALL - { - // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE - // assertions are reported without translation at the point of origin. - if (m_shouldReportUnexpected) { - AssertionReaction dummyReaction; - handleUnexpectedInflightException( - m_lastAssertionInfo, translateActiveException(), dummyReaction); - } - } - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions(assertions); - - m_testCaseTracker->close(); - handleUnfinishedSections(); - m_messages.clear(); - m_messageScopes.clear(); - - SectionStats testCaseSectionStats( - testCaseSection, assertions, duration, missingAssertions); - m_reporter->sectionEnded(testCaseSectionStats); -} - -void RunContext::invokeActiveTestCase() -{ - FatalConditionHandlerGuard _(&m_fatalConditionhandler); - m_activeTestCase->invoke(); -} - -void RunContext::handleUnfinishedSections() -{ - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for (auto it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); - it != itEnd; ++it) - sectionEnded(*it); - m_unfinishedSections.clear(); -} - -void RunContext::handleExpr(AssertionInfo const &info, - ITransientExpression const &expr, AssertionReaction &reaction) -{ - m_reporter->assertionStarting(info); - - bool negated = isFalseTest(info.resultDisposition); - bool result = expr.getResult() != negated; - - if (result) { - if (!m_includeSuccessfulResults) { - assertionPassed(); - } - else { - reportExpr(info, ResultWas::Ok, &expr, negated); - } - } - else { - reportExpr(info, ResultWas::ExpressionFailed, &expr, negated); - populateReaction(reaction); - } -} -void RunContext::reportExpr(AssertionInfo const &info, - ResultWas::OfType resultType, ITransientExpression const *expr, - bool negated) -{ - - m_lastAssertionInfo = info; - AssertionResultData data(resultType, LazyExpression(negated)); - - AssertionResult assertionResult{info, data}; - assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; - - assertionEnded(assertionResult); -} - -void RunContext::handleMessage(AssertionInfo const &info, - ResultWas::OfType resultType, StringRef const &message, - AssertionReaction &reaction) -{ - m_reporter->assertionStarting(info); - - m_lastAssertionInfo = info; - - AssertionResultData data(resultType, LazyExpression(false)); - data.message = static_cast(message); - AssertionResult assertionResult{m_lastAssertionInfo, data}; - assertionEnded(assertionResult); - if (!assertionResult.isOk()) - populateReaction(reaction); -} -void RunContext::handleUnexpectedExceptionNotThrown( - AssertionInfo const &info, AssertionReaction &reaction) -{ - handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction); -} - -void RunContext::handleUnexpectedInflightException(AssertionInfo const &info, - std::string const &message, AssertionReaction &reaction) -{ - m_lastAssertionInfo = info; - - AssertionResultData data(ResultWas::ThrewException, LazyExpression(false)); - data.message = message; - AssertionResult assertionResult{info, data}; - assertionEnded(assertionResult); - populateReaction(reaction); -} - -void RunContext::populateReaction(AssertionReaction &reaction) -{ - reaction.shouldDebugBreak = m_config->shouldDebugBreak(); - reaction.shouldThrow = aborting() || - (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal); -} - -void RunContext::handleIncomplete(AssertionInfo const &info) -{ - m_lastAssertionInfo = info; - - AssertionResultData data(ResultWas::ThrewException, LazyExpression(false)); - data.message = - "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; - AssertionResult assertionResult{info, data}; - assertionEnded(assertionResult); -} -void RunContext::handleNonExpr(AssertionInfo const &info, - ResultWas::OfType resultType, AssertionReaction &reaction) -{ - m_lastAssertionInfo = info; - - AssertionResultData data(resultType, LazyExpression(false)); - AssertionResult assertionResult{info, data}; - assertionEnded(assertionResult); - - if (!assertionResult.isOk()) - populateReaction(reaction); -} - -IResultCapture &getResultCapture() -{ - if (auto *capture = getCurrentContext().getResultCapture()) - return *capture; - else - CATCH_INTERNAL_ERROR("No result capture instance"); -} - -void seedRng(IConfig const &config) -{ - if (config.rngSeed() != 0) { - std::srand(config.rngSeed()); - rng().seed(config.rngSeed()); - } -} - -unsigned int rngSeed() { return getCurrentContext().getConfig()->rngSeed(); } - -} -// end catch_run_context.cpp -// start catch_section.cpp - -namespace Catch { - -Section::Section(SectionInfo const &info) - : m_info(info) - , m_sectionIncluded(getResultCapture().sectionStarted(m_info, m_assertions)) -{ - m_timer.start(); -} - -Section::~Section() -{ - if (m_sectionIncluded) { - SectionEndInfo endInfo{ - m_info, m_assertions, m_timer.getElapsedSeconds()}; - if (uncaught_exceptions()) - getResultCapture().sectionEndedEarly(endInfo); - else - getResultCapture().sectionEnded(endInfo); - } -} - -// This indicates whether the section should be executed or not -Section::operator bool() const { return m_sectionIncluded; } - -} // end namespace Catch -// end catch_section.cpp -// start catch_section_info.cpp - -namespace Catch { - -SectionInfo::SectionInfo( - SourceLineInfo const &_lineInfo, std::string const &_name) - : name(_name) - , lineInfo(_lineInfo) -{ -} - -} // end namespace Catch -// end catch_section_info.cpp -// start catch_session.cpp - -// start catch_session.h - -#include - -namespace Catch { - -class Session : NonCopyable { -public: - Session(); - ~Session() override; - - void showHelp() const; - void libIdentify(); - - int applyCommandLine(int argc, char const *const *argv); -#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) - int applyCommandLine(int argc, wchar_t const *const *argv); -#endif - - void useConfigData(ConfigData const &configData); - - template int run(int argc, CharT const *const argv[]) - { - if (m_startupExceptions) - return 1; - int returnCode = applyCommandLine(argc, argv); - if (returnCode == 0) - returnCode = run(); - return returnCode; - } - - int run(); - - clara::Parser const &cli() const; - void cli(clara::Parser const &newParser); - ConfigData &configData(); - Config &config(); - -private: - int runInternal(); - - clara::Parser m_cli; - ConfigData m_configData; - std::shared_ptr m_config; - bool m_startupExceptions = false; -}; - -} // end namespace Catch - -// end catch_session.h -// start catch_version.h - -#include - -namespace Catch { - -// Versioning information -struct Version { - Version(Version const &) = delete; - Version &operator=(Version const &) = delete; - Version(unsigned int _majorVersion, unsigned int _minorVersion, - unsigned int _patchNumber, char const *const _branchName, - unsigned int _buildNumber); - - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const patchNumber; - - // buildNumber is only used if branchName is not null - char const *const branchName; - unsigned int const buildNumber; - - friend std::ostream &operator<<(std::ostream &os, Version const &version); -}; - -Version const &libraryVersion(); -} - -// end catch_version.h -#include -#include -#include -#include - -namespace Catch { - -namespace { -const int MaxExitCode = 255; - -IStreamingReporterPtr createReporter( - std::string const &reporterName, IConfigPtr const &config) -{ - auto reporter = Catch::getRegistryHub().getReporterRegistry().create( - reporterName, config); - CATCH_ENFORCE( - reporter, "No reporter registered with name: '" << reporterName << "'"); - - return reporter; -} - -IStreamingReporterPtr makeReporter(std::shared_ptr const &config) -{ - if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { - return createReporter(config->getReporterName(), config); - } - - // On older platforms, returning std::unique_ptr - // when the return type is std::unique_ptr - // doesn't compile without a std::move call. However, this causes - // a warning on newer platforms. Thus, we have to work around - // it a bit and downcast the pointer manually. - auto ret = std::unique_ptr(new ListeningReporter); - auto &multi = static_cast(*ret); - auto const &listeners = - Catch::getRegistryHub().getReporterRegistry().getListeners(); - for (auto const &listener : listeners) { - multi.addListener(listener->create(Catch::ReporterConfig(config))); - } - multi.addReporter(createReporter(config->getReporterName(), config)); - return ret; -} - -class TestGroup { -public: - explicit TestGroup(std::shared_ptr const &config) - : m_config{config} - , m_context{config, makeReporter(config)} - { - auto const &allTestCases = getAllTestCasesSorted(*m_config); - m_matches = - m_config->testSpec().matchesByFilter(allTestCases, *m_config); - auto const &invalidArgs = m_config->testSpec().getInvalidArgs(); - - if (m_matches.empty() && invalidArgs.empty()) { - for (auto const &test : allTestCases) - if (!test.isHidden()) - m_tests.emplace(&test); - } - else { - for (auto const &match : m_matches) - m_tests.insert(match.tests.begin(), match.tests.end()); - } - } - - Totals execute() - { - auto const &invalidArgs = m_config->testSpec().getInvalidArgs(); - Totals totals; - m_context.testGroupStarting(m_config->name(), 1, 1); - for (auto const &testCase : m_tests) { - if (!m_context.aborting()) - totals += m_context.runTest(*testCase); - else - m_context.reporter().skipTest(*testCase); - } - - for (auto const &match : m_matches) { - if (match.tests.empty()) { - m_context.reporter().noMatchingTestCases(match.name); - totals.error = -1; - } - } - - if (!invalidArgs.empty()) { - for (auto const &invalidArg : invalidArgs) - m_context.reporter().reportInvalidArguments(invalidArg); - } - - m_context.testGroupEnded(m_config->name(), totals, 1, 1); - return totals; - } - -private: - using Tests = std::set; - - std::shared_ptr m_config; - RunContext m_context; - Tests m_tests; - TestSpec::Matches m_matches; -}; - -void applyFilenamesAsTags(Catch::IConfig const &config) -{ - auto &tests = - const_cast &>(getAllTestCasesSorted(config)); - for (auto &testCase : tests) { - auto tags = testCase.tags; - - std::string filename = testCase.lineInfo.file; - auto lastSlash = filename.find_last_of("\\/"); - if (lastSlash != std::string::npos) { - filename.erase(0, lastSlash); - filename[0] = '#'; - } - - auto lastDot = filename.find_last_of('.'); - if (lastDot != std::string::npos) { - filename.erase(lastDot); - } - - tags.push_back(std::move(filename)); - setTags(testCase, tags); - } -} - -} // anon namespace - -Session::Session() -{ - static bool alreadyInstantiated = false; - if (alreadyInstantiated) { - CATCH_TRY - { - CATCH_INTERNAL_ERROR( - "Only one instance of Catch::Session can ever be used"); - } - CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); } - } - - // There cannot be exceptions at startup in no-exception mode. -#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - const auto &exceptions = - getRegistryHub().getStartupExceptionRegistry().getExceptions(); - if (!exceptions.empty()) { - config(); - getCurrentMutableContext().setConfig(m_config); - - m_startupExceptions = true; - Colour colourGuard(Colour::Red); - Catch::cerr() << "Errors occurred during startup!" << '\n'; - // iterate over all exceptions and notify user - for (const auto &ex_ptr : exceptions) { - try { - std::rethrow_exception(ex_ptr); - } - catch (std::exception const &ex) { - Catch::cerr() << Column(ex.what()).indent(2) << '\n'; - } - } - } -#endif - - alreadyInstantiated = true; - m_cli = makeCommandLineParser(m_configData); -} -Session::~Session() { Catch::cleanUp(); } - -void Session::showHelp() const -{ - Catch::cout() << "\nCatch v" << libraryVersion() << "\n" - << m_cli << std::endl - << "For more detailed usage please see the project docs\n" - << std::endl; -} -void Session::libIdentify() -{ - Catch::cout() << std::left << std::setw(16) << "description: " - << "A Catch2 test executable\n" - << std::left << std::setw(16) << "category: " - << "testframework\n" - << std::left << std::setw(16) << "framework: " - << "Catch Test\n" - << std::left << std::setw(16) - << "version: " << libraryVersion() << std::endl; -} - -int Session::applyCommandLine(int argc, char const *const *argv) -{ - if (m_startupExceptions) - return 1; - - auto result = m_cli.parse(clara::Args(argc, argv)); - if (!result) { - config(); - getCurrentMutableContext().setConfig(m_config); - Catch::cerr() << Colour(Colour::Red) << "\nError(s) in input:\n" - << Column(result.errorMessage()).indent(2) << "\n\n"; - Catch::cerr() << "Run with -? for usage\n" << std::endl; - return MaxExitCode; - } - - if (m_configData.showHelp) - showHelp(); - if (m_configData.libIdentify) - libIdentify(); - m_config.reset(); - return 0; -} - -#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) -int Session::applyCommandLine(int argc, wchar_t const *const *argv) -{ - - char **utf8Argv = new char *[argc]; - - for (int i = 0; i < argc; ++i) { - int bufSize = WideCharToMultiByte( - CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr); - - utf8Argv[i] = new char[bufSize]; - - WideCharToMultiByte( - CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr); - } - - int returnCode = applyCommandLine(argc, utf8Argv); - - for (int i = 0; i < argc; ++i) - delete[] utf8Argv[i]; - - delete[] utf8Argv; - - return returnCode; -} -#endif - -void Session::useConfigData(ConfigData const &configData) -{ - m_configData = configData; - m_config.reset(); -} - -int Session::run() -{ - if ((m_configData.waitForKeypress & WaitForKeypress::BeforeStart) != 0) { - Catch::cout() << "...waiting for enter/ return before starting" - << std::endl; - static_cast(std::getchar()); - } - int exitCode = runInternal(); - if ((m_configData.waitForKeypress & WaitForKeypress::BeforeExit) != 0) { - Catch::cout() - << "...waiting for enter/ return before exiting, with code: " - << exitCode << std::endl; - static_cast(std::getchar()); - } - return exitCode; -} - -clara::Parser const &Session::cli() const { return m_cli; } -void Session::cli(clara::Parser const &newParser) { m_cli = newParser; } -ConfigData &Session::configData() { return m_configData; } -Config &Session::config() -{ - if (!m_config) - m_config = std::make_shared(m_configData); - return *m_config; -} - -int Session::runInternal() -{ - if (m_startupExceptions) - return 1; - - if (m_configData.showHelp || m_configData.libIdentify) { - return 0; - } - - CATCH_TRY - { - config(); // Force config to be constructed - - seedRng(*m_config); - - if (m_configData.filenamesAsTags) - applyFilenamesAsTags(*m_config); - - // Handle list request - if (Option listed = list(m_config)) - return static_cast(*listed); - - TestGroup tests{m_config}; - auto const totals = tests.execute(); - - if (m_config->warnAboutNoTests() && totals.error == -1) - return 2; - - // Note that on unices only the lower 8 bits are usually used, clamping - // the return value to 255 prevents false negative when some multiple - // of 256 tests has failed - return (std::min)(MaxExitCode, - (std::max)( - totals.error, static_cast(totals.assertions.failed))); - } -#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - catch (std::exception &ex) - { - Catch::cerr() << ex.what() << std::endl; - return MaxExitCode; - } -#endif -} - -} // end namespace Catch -// end catch_session.cpp -// start catch_singletons.cpp - -#include - -namespace Catch { - -namespace { -static auto getSingletons() -> std::vector *& -{ - static std::vector *g_singletons = nullptr; - if (!g_singletons) - g_singletons = new std::vector(); - return g_singletons; -} -} - -ISingleton::~ISingleton() { } - -void addSingleton(ISingleton *singleton) -{ - getSingletons()->push_back(singleton); -} -void cleanupSingletons() -{ - auto &singletons = getSingletons(); - for (auto singleton : *singletons) - delete singleton; - delete singletons; - singletons = nullptr; -} - -} // namespace Catch -// end catch_singletons.cpp -// start catch_startup_exception_registry.cpp - -#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -namespace Catch { -void StartupExceptionRegistry::add(std::exception_ptr const &exception) noexcept -{ - CATCH_TRY { m_exceptions.push_back(exception); } - CATCH_CATCH_ALL - { - // If we run out of memory during start-up there's really not a lot more - // we can do about it - std::terminate(); - } -} - -std::vector const & -StartupExceptionRegistry::getExceptions() const noexcept -{ - return m_exceptions; -} - -} // end namespace Catch -#endif -// end catch_startup_exception_registry.cpp -// start catch_stream.cpp - -#include -#include -#include -#include -#include -#include - -namespace Catch { - -Catch::IStream::~IStream() = default; - -namespace Detail { -namespace { -template -class StreamBufImpl : public std::streambuf { - char data[bufferSize]; - WriterF m_writer; - -public: - StreamBufImpl() { setp(data, data + sizeof(data)); } - - ~StreamBufImpl() noexcept { StreamBufImpl::sync(); } - -private: - int overflow(int c) override - { - sync(); - - if (c != EOF) { - if (pbase() == epptr()) - m_writer(std::string(1, static_cast(c))); - else - sputc(static_cast(c)); - } - return 0; - } - - int sync() override - { - if (pbase() != pptr()) { - m_writer(std::string(pbase(), - static_cast(pptr() - pbase()))); - setp(pbase(), epptr()); - } - return 0; - } -}; - -/////////////////////////////////////////////////////////////////////////// - -struct OutputDebugWriter { - - void operator()(std::string const &str) { writeToDebugConsole(str); } -}; - -/////////////////////////////////////////////////////////////////////////// - -class FileStream : public IStream { - mutable std::ofstream m_ofs; - -public: - FileStream(StringRef filename) - { - m_ofs.open(filename.c_str()); - CATCH_ENFORCE( - !m_ofs.fail(), "Unable to open file: '" << filename << "'"); - } - ~FileStream() override = default; - -public: // IStream - std::ostream &stream() const override { return m_ofs; } -}; - -/////////////////////////////////////////////////////////////////////////// - -class CoutStream : public IStream { - mutable std::ostream m_os; - -public: - // Store the streambuf from cout up-front because - // cout may get redirected when running tests - CoutStream() - : m_os(Catch::cout().rdbuf()) - { - } - ~CoutStream() override = default; - -public: // IStream - std::ostream &stream() const override { return m_os; } -}; - -/////////////////////////////////////////////////////////////////////////// - -class DebugOutStream : public IStream { - std::unique_ptr> m_streamBuf; - mutable std::ostream m_os; - -public: - DebugOutStream() - : m_streamBuf(new StreamBufImpl()) - , m_os(m_streamBuf.get()) - { - } - - ~DebugOutStream() override = default; - -public: // IStream - std::ostream &stream() const override { return m_os; } -}; - -} -} // namespace anon::detail - -/////////////////////////////////////////////////////////////////////////// - -auto makeStream(StringRef const &filename) -> IStream const * -{ - if (filename.empty()) - return new Detail::CoutStream(); - else if (filename[0] == '%') { - if (filename == "%debug") - return new Detail::DebugOutStream(); - else - CATCH_ERROR("Unrecognised stream: '" << filename << "'"); - } - else - return new Detail::FileStream(filename); -} - -// This class encapsulates the idea of a pool of ostringstreams that can be -// reused. -struct StringStreams { - std::vector> m_streams; - std::vector m_unused; - std::ostringstream m_referenceStream; // Used for copy state/ flags from - - auto add() -> std::size_t - { - if (m_unused.empty()) { - m_streams.push_back( - std::unique_ptr(new std::ostringstream)); - return m_streams.size() - 1; - } - else { - auto index = m_unused.back(); - m_unused.pop_back(); - return index; - } - } - - void release(std::size_t index) - { - m_streams[index]->copyfmt( - m_referenceStream); // Restore initial flags and other state - m_unused.push_back(index); - } -}; - -ReusableStringStream::ReusableStringStream() - : m_index(Singleton::getMutable().add()) - , m_oss(Singleton::getMutable().m_streams[m_index].get()) -{ -} - -ReusableStringStream::~ReusableStringStream() -{ - static_cast(m_oss)->str(""); - m_oss->clear(); - Singleton::getMutable().release(m_index); -} - -auto ReusableStringStream::str() const -> std::string -{ - return static_cast(m_oss)->str(); -} - -/////////////////////////////////////////////////////////////////////////// - -#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these - // functions -std::ostream &cout() { return std::cout; } -std::ostream &cerr() { return std::cerr; } -std::ostream &clog() { return std::clog; } -#endif -} -// end catch_stream.cpp -// start catch_string_manip.cpp - -#include -#include -#include -#include -#include - -namespace Catch { - -namespace { -char toLowerCh(char c) -{ - return static_cast(std::tolower(static_cast(c))); -} -} - -bool startsWith(std::string const &s, std::string const &prefix) -{ - return s.size() >= prefix.size() && - std::equal(prefix.begin(), prefix.end(), s.begin()); -} -bool startsWith(std::string const &s, char prefix) -{ - return !s.empty() && s[0] == prefix; -} -bool endsWith(std::string const &s, std::string const &suffix) -{ - return s.size() >= suffix.size() && - std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); -} -bool endsWith(std::string const &s, char suffix) -{ - return !s.empty() && s[s.size() - 1] == suffix; -} -bool contains(std::string const &s, std::string const &infix) -{ - return s.find(infix) != std::string::npos; -} -void toLowerInPlace(std::string &s) -{ - std::transform(s.begin(), s.end(), s.begin(), toLowerCh); -} -std::string toLower(std::string const &s) -{ - std::string lc = s; - toLowerInPlace(lc); - return lc; -} -std::string trim(std::string const &str) -{ - static char const *whitespaceChars = "\n\r\t "; - std::string::size_type start = str.find_first_not_of(whitespaceChars); - std::string::size_type end = str.find_last_not_of(whitespaceChars); - - return start != std::string::npos ? str.substr(start, 1 + end - start) - : std::string(); -} - -StringRef trim(StringRef ref) -{ - const auto is_ws = [](char c) { - return c == ' ' || c == '\t' || c == '\n' || c == '\r'; - }; - size_t real_begin = 0; - while (real_begin < ref.size() && is_ws(ref[real_begin])) { - ++real_begin; - } - size_t real_end = ref.size(); - while (real_end > real_begin && is_ws(ref[real_end - 1])) { - --real_end; - } - - return ref.substr(real_begin, real_end - real_begin); -} - -bool replaceInPlace(std::string &str, std::string const &replaceThis, - std::string const &withThis) -{ - bool replaced = false; - std::size_t i = str.find(replaceThis); - while (i != std::string::npos) { - replaced = true; - str = str.substr(0, i) + withThis + str.substr(i + replaceThis.size()); - if (i < str.size() - withThis.size()) - i = str.find(replaceThis, i + withThis.size()); - else - i = std::string::npos; - } - return replaced; -} - -std::vector splitStringRef(StringRef str, char delimiter) -{ - std::vector subStrings; - std::size_t start = 0; - for (std::size_t pos = 0; pos < str.size(); ++pos) { - if (str[pos] == delimiter) { - if (pos - start > 1) - subStrings.push_back(str.substr(start, pos - start)); - start = pos + 1; - } - } - if (start < str.size()) - subStrings.push_back(str.substr(start, str.size() - start)); - return subStrings; -} - -pluralise::pluralise(std::size_t count, std::string const &label) - : m_count(count) - , m_label(label) -{ -} - -std::ostream &operator<<(std::ostream &os, pluralise const &pluraliser) -{ - os << pluraliser.m_count << ' ' << pluraliser.m_label; - if (pluraliser.m_count != 1) - os << 's'; - return os; -} - -} -// end catch_string_manip.cpp -// start catch_stringref.cpp - -#include -#include -#include -#include - -namespace Catch { -StringRef::StringRef(char const *rawChars) noexcept - : StringRef( - rawChars, static_cast(std::strlen(rawChars))) -{ -} - -auto StringRef::c_str() const -> char const * -{ - CATCH_ENFORCE(isNullTerminated(), - "Called StringRef::c_str() on a non-null-terminated instance"); - return m_start; -} -auto StringRef::data() const noexcept -> char const * { return m_start; } - -auto StringRef::substr(size_type start, size_type size) const noexcept - -> StringRef -{ - if (start < m_size) { - return StringRef(m_start + start, (std::min)(m_size - start, size)); - } - else { - return StringRef(); - } -} -auto StringRef::operator==(StringRef const &other) const noexcept -> bool -{ - return m_size == other.m_size && - (std::memcmp(m_start, other.m_start, m_size) == 0); -} - -auto operator<<(std::ostream &os, StringRef const &str) -> std::ostream & -{ - return os.write(str.data(), str.size()); -} - -auto operator+=(std::string &lhs, StringRef const &rhs) -> std::string & -{ - lhs.append(rhs.data(), rhs.size()); - return lhs; -} - -} // namespace Catch -// end catch_stringref.cpp -// start catch_tag_alias.cpp - -namespace Catch { -TagAlias::TagAlias(std::string const &_tag, SourceLineInfo _lineInfo) - : tag(_tag) - , lineInfo(_lineInfo) -{ -} -} -// end catch_tag_alias.cpp -// start catch_tag_alias_autoregistrar.cpp - -namespace Catch { - -RegistrarForTagAliases::RegistrarForTagAliases( - char const *alias, char const *tag, SourceLineInfo const &lineInfo) -{ - CATCH_TRY - { - getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); - } - CATCH_CATCH_ALL - { - // Do not throw when constructing global objects, instead register the - // exception to be processed later - getMutableRegistryHub().registerStartupException(); - } -} - -} -// end catch_tag_alias_autoregistrar.cpp -// start catch_tag_alias_registry.cpp - -#include - -namespace Catch { - -TagAliasRegistry::~TagAliasRegistry() { } - -TagAlias const *TagAliasRegistry::find(std::string const &alias) const -{ - auto it = m_registry.find(alias); - if (it != m_registry.end()) - return &(it->second); - else - return nullptr; -} - -std::string TagAliasRegistry::expandAliases( - std::string const &unexpandedTestSpec) const -{ - std::string expandedTestSpec = unexpandedTestSpec; - for (auto const ®istryKvp : m_registry) { - std::size_t pos = expandedTestSpec.find(registryKvp.first); - if (pos != std::string::npos) { - expandedTestSpec = expandedTestSpec.substr(0, pos) + - registryKvp.second.tag + - expandedTestSpec.substr(pos + registryKvp.first.size()); - } - } - return expandedTestSpec; -} - -void TagAliasRegistry::add(std::string const &alias, std::string const &tag, - SourceLineInfo const &lineInfo) -{ - CATCH_ENFORCE(startsWith(alias, "[@") && endsWith(alias, ']'), - "error: tag alias, '" << alias - << "' is not of the form [@alias name].\n" - << lineInfo); - - CATCH_ENFORCE( - m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))) - .second, - "error: tag alias, '" << alias << "' already registered.\n" - << "\tFirst seen at: " << find(alias)->lineInfo - << "\n" - << "\tRedefined at: " << lineInfo); -} - -ITagAliasRegistry::~ITagAliasRegistry() { } - -ITagAliasRegistry const &ITagAliasRegistry::get() -{ - return getRegistryHub().getTagAliasRegistry(); -} - -} // end namespace Catch -// end catch_tag_alias_registry.cpp -// start catch_test_case_info.cpp - -#include -#include -#include -#include - -namespace Catch { - -namespace { -TestCaseInfo::SpecialProperties parseSpecialTag(std::string const &tag) -{ - if (startsWith(tag, '.') || tag == "!hide") - return TestCaseInfo::IsHidden; - else if (tag == "!throws") - return TestCaseInfo::Throws; - else if (tag == "!shouldfail") - return TestCaseInfo::ShouldFail; - else if (tag == "!mayfail") - return TestCaseInfo::MayFail; - else if (tag == "!nonportable") - return TestCaseInfo::NonPortable; - else if (tag == "!benchmark") - return static_cast( - TestCaseInfo::Benchmark | TestCaseInfo::IsHidden); - else - return TestCaseInfo::None; -} -bool isReservedTag(std::string const &tag) -{ - return parseSpecialTag(tag) == TestCaseInfo::None && tag.size() > 0 && - !std::isalnum(static_cast(tag[0])); -} -void enforceNotReservedTag( - std::string const &tag, SourceLineInfo const &_lineInfo) -{ - CATCH_ENFORCE(!isReservedTag(tag), - "Tag name: [" << tag << "] is not allowed.\n" - << "Tag names starting with non alphanumeric characters " - "are reserved\n" - << _lineInfo); -} -} - -TestCase makeTestCase(ITestInvoker *_testCase, std::string const &_className, - NameAndTags const &nameAndTags, SourceLineInfo const &_lineInfo) -{ - bool isHidden = false; - - // Parse out tags - std::vector tags; - std::string desc, tag; - bool inTag = false; - for (char c : nameAndTags.tags) { - if (!inTag) { - if (c == '[') - inTag = true; - else - desc += c; - } - else { - if (c == ']') { - TestCaseInfo::SpecialProperties prop = parseSpecialTag(tag); - if ((prop & TestCaseInfo::IsHidden) != 0) - isHidden = true; - else if (prop == TestCaseInfo::None) - enforceNotReservedTag(tag, _lineInfo); - - // Merged hide tags like `[.approvals]` should be added as - // `[.][approvals]`. The `[.]` is added at later point, so - // we only strip the prefix - if (startsWith(tag, '.') && tag.size() > 1) { - tag.erase(0, 1); - } - tags.push_back(tag); - tag.clear(); - inTag = false; - } - else - tag += c; - } - } - if (isHidden) { - // Add all "hidden" tags to make them behave identically - tags.insert(tags.end(), {".", "!hide"}); - } - - TestCaseInfo info(static_cast(nameAndTags.name), _className, - desc, tags, _lineInfo); - return TestCase(_testCase, std::move(info)); -} - -void setTags(TestCaseInfo &testCaseInfo, std::vector tags) -{ - std::sort(begin(tags), end(tags)); - tags.erase(std::unique(begin(tags), end(tags)), end(tags)); - testCaseInfo.lcaseTags.clear(); - - for (auto const &tag : tags) { - std::string lcaseTag = toLower(tag); - testCaseInfo.properties = static_cast( - testCaseInfo.properties | parseSpecialTag(lcaseTag)); - testCaseInfo.lcaseTags.push_back(lcaseTag); - } - testCaseInfo.tags = std::move(tags); -} - -TestCaseInfo::TestCaseInfo(std::string const &_name, - std::string const &_className, std::string const &_description, - std::vector const &_tags, SourceLineInfo const &_lineInfo) - : name(_name) - , className(_className) - , description(_description) - , lineInfo(_lineInfo) - , properties(None) -{ - setTags(*this, _tags); -} - -bool TestCaseInfo::isHidden() const { return (properties & IsHidden) != 0; } -bool TestCaseInfo::throws() const { return (properties & Throws) != 0; } -bool TestCaseInfo::okToFail() const -{ - return (properties & (ShouldFail | MayFail)) != 0; -} -bool TestCaseInfo::expectedToFail() const -{ - return (properties & (ShouldFail)) != 0; -} - -std::string TestCaseInfo::tagsAsString() const -{ - std::string ret; - // '[' and ']' per tag - std::size_t full_size = 2 * tags.size(); - for (const auto &tag : tags) { - full_size += tag.size(); - } - ret.reserve(full_size); - for (const auto &tag : tags) { - ret.push_back('['); - ret.append(tag); - ret.push_back(']'); - } - - return ret; -} - -TestCase::TestCase(ITestInvoker *testCase, TestCaseInfo &&info) - : TestCaseInfo(std::move(info)) - , test(testCase) -{ -} - -TestCase TestCase::withName(std::string const &_newName) const -{ - TestCase other(*this); - other.name = _newName; - return other; -} - -void TestCase::invoke() const { test->invoke(); } - -bool TestCase::operator==(TestCase const &other) const -{ - return test.get() == other.test.get() && name == other.name && - className == other.className; -} - -bool TestCase::operator<(TestCase const &other) const -{ - return name < other.name; -} - -TestCaseInfo const &TestCase::getTestCaseInfo() const { return *this; } - -} // end namespace Catch -// end catch_test_case_info.cpp -// start catch_test_case_registry_impl.cpp - -#include -#include - -namespace Catch { - -namespace { -struct TestHasher { - using hash_t = uint64_t; - - explicit TestHasher(hash_t hashSuffix) - : m_hashSuffix{hashSuffix} - { - } - - uint32_t operator()(TestCase const &t) const - { - // FNV-1a hash with multiplication fold. - const hash_t prime = 1099511628211u; - hash_t hash = 14695981039346656037u; - for (const char c : t.name) { - hash ^= c; - hash *= prime; - } - hash ^= m_hashSuffix; - hash *= prime; - const uint32_t low{static_cast(hash)}; - const uint32_t high{static_cast(hash >> 32)}; - return low * high; - } - -private: - hash_t m_hashSuffix; -}; -} // end unnamed namespace - -std::vector sortTests( - IConfig const &config, std::vector const &unsortedTestCases) -{ - switch (config.runOrder()) { - case RunTests::InDeclarationOrder: - // already in declaration order - break; - - case RunTests::InLexicographicalOrder: { - std::vector sorted = unsortedTestCases; - std::sort(sorted.begin(), sorted.end()); - return sorted; - } - - case RunTests::InRandomOrder: { - seedRng(config); - TestHasher h{config.rngSeed()}; - - using hashedTest = std::pair; - std::vector indexed_tests; - indexed_tests.reserve(unsortedTestCases.size()); - - for (auto const &testCase : unsortedTestCases) { - indexed_tests.emplace_back(h(testCase), &testCase); - } - - std::sort(indexed_tests.begin(), indexed_tests.end(), - [](hashedTest const &lhs, hashedTest const &rhs) { - if (lhs.first == rhs.first) { - return lhs.second->name < rhs.second->name; - } - return lhs.first < rhs.first; - }); - - std::vector sorted; - sorted.reserve(indexed_tests.size()); - - for (auto const &hashed : indexed_tests) { - sorted.emplace_back(*hashed.second); - } - - return sorted; - } - } - return unsortedTestCases; -} - -bool isThrowSafe(TestCase const &testCase, IConfig const &config) -{ - return !testCase.throws() || config.allowThrows(); -} - -bool matchTest( - TestCase const &testCase, TestSpec const &testSpec, IConfig const &config) -{ - return testSpec.matches(testCase) && isThrowSafe(testCase, config); -} - -void enforceNoDuplicateTestCases(std::vector const &functions) -{ - std::set seenFunctions; - for (auto const &function : functions) { - auto prev = seenFunctions.insert(function); - CATCH_ENFORCE(prev.second, - "error: TEST_CASE( \"" - << function.name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo - << "\n" - << "\tRedefined at " << function.getTestCaseInfo().lineInfo); - } -} - -std::vector filterTests(std::vector const &testCases, - TestSpec const &testSpec, IConfig const &config) -{ - std::vector filtered; - filtered.reserve(testCases.size()); - for (auto const &testCase : testCases) { - if ((!testSpec.hasFilters() && !testCase.isHidden()) || - (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) { - filtered.push_back(testCase); - } - } - return filtered; -} -std::vector const &getAllTestCasesSorted(IConfig const &config) -{ - return getRegistryHub().getTestCaseRegistry().getAllTestsSorted(config); -} - -void TestRegistry::registerTest(TestCase const &testCase) -{ - std::string name = testCase.getTestCaseInfo().name; - if (name.empty()) { - ReusableStringStream rss; - rss << "Anonymous test case " << ++m_unnamedCount; - return registerTest(testCase.withName(rss.str())); - } - m_functions.push_back(testCase); -} - -std::vector const &TestRegistry::getAllTests() const -{ - return m_functions; -} -std::vector const &TestRegistry::getAllTestsSorted( - IConfig const &config) const -{ - if (m_sortedFunctions.empty()) - enforceNoDuplicateTestCases(m_functions); - - if (m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty()) { - m_sortedFunctions = sortTests(config, m_functions); - m_currentSortOrder = config.runOrder(); - } - return m_sortedFunctions; -} - -/////////////////////////////////////////////////////////////////////////// -TestInvokerAsFunction::TestInvokerAsFunction(void (*testAsFunction)()) noexcept - : m_testAsFunction(testAsFunction) -{ -} - -void TestInvokerAsFunction::invoke() const { m_testAsFunction(); } - -std::string extractClassName(StringRef const &classOrQualifiedMethodName) -{ - std::string className(classOrQualifiedMethodName); - if (startsWith(className, '&')) { - std::size_t lastColons = className.rfind("::"); - std::size_t penultimateColons = className.rfind("::", lastColons - 1); - if (penultimateColons == std::string::npos) - penultimateColons = 1; - className = - className.substr(penultimateColons, lastColons - penultimateColons); - } - return className; -} - -} // end namespace Catch -// end catch_test_case_registry_impl.cpp -// start catch_test_case_tracker.cpp - -#include -#include -#include -#include -#include - -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wexit-time-destructors" -#endif - -namespace Catch { -namespace TestCaseTracking { - -NameAndLocation::NameAndLocation( - std::string const &_name, SourceLineInfo const &_location) - : name(_name) - , location(_location) -{ -} - -ITracker::~ITracker() = default; - -ITracker &TrackerContext::startRun() -{ - m_rootTracker = std::make_shared( - NameAndLocation("{root}", CATCH_INTERNAL_LINEINFO), *this, nullptr); - m_currentTracker = nullptr; - m_runState = Executing; - return *m_rootTracker; -} - -void TrackerContext::endRun() -{ - m_rootTracker.reset(); - m_currentTracker = nullptr; - m_runState = NotStarted; -} - -void TrackerContext::startCycle() -{ - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; -} -void TrackerContext::completeCycle() { m_runState = CompletedCycle; } - -bool TrackerContext::completedCycle() const -{ - return m_runState == CompletedCycle; -} -ITracker &TrackerContext::currentTracker() { return *m_currentTracker; } -void TrackerContext::setCurrentTracker(ITracker *tracker) -{ - m_currentTracker = tracker; -} - -TrackerBase::TrackerBase(NameAndLocation const &nameAndLocation, - TrackerContext &ctx, ITracker *parent) - : ITracker(nameAndLocation) - , m_ctx(ctx) - , m_parent(parent) -{ -} - -bool TrackerBase::isComplete() const -{ - return m_runState == CompletedSuccessfully || m_runState == Failed; -} -bool TrackerBase::isSuccessfullyCompleted() const -{ - return m_runState == CompletedSuccessfully; -} -bool TrackerBase::isOpen() const -{ - return m_runState != NotStarted && !isComplete(); -} -bool TrackerBase::hasChildren() const { return !m_children.empty(); } - -void TrackerBase::addChild(ITrackerPtr const &child) -{ - m_children.push_back(child); -} - -ITrackerPtr TrackerBase::findChild(NameAndLocation const &nameAndLocation) -{ - auto it = std::find_if(m_children.begin(), m_children.end(), - [&nameAndLocation](ITrackerPtr const &tracker) { - return tracker->nameAndLocation().location == - nameAndLocation.location && - tracker->nameAndLocation().name == nameAndLocation.name; - }); - return (it != m_children.end()) ? *it : nullptr; -} -ITracker &TrackerBase::parent() -{ - assert(m_parent); // Should always be non-null except for root - return *m_parent; -} - -void TrackerBase::openChild() -{ - if (m_runState != ExecutingChildren) { - m_runState = ExecutingChildren; - if (m_parent) - m_parent->openChild(); - } -} - -bool TrackerBase::isSectionTracker() const { return false; } -bool TrackerBase::isGeneratorTracker() const { return false; } - -void TrackerBase::open() -{ - m_runState = Executing; - moveToThis(); - if (m_parent) - m_parent->openChild(); -} - -void TrackerBase::close() -{ - - // Close any still open children (e.g. generators) - while (&m_ctx.currentTracker() != this) - m_ctx.currentTracker().close(); - - switch (m_runState) { - case NeedsAnotherRun: - break; - - case Executing: - m_runState = CompletedSuccessfully; - break; - case ExecutingChildren: - if (std::all_of(m_children.begin(), m_children.end(), - [](ITrackerPtr const &t) { return t->isComplete(); })) - m_runState = CompletedSuccessfully; - break; - - case NotStarted: - case CompletedSuccessfully: - case Failed: - CATCH_INTERNAL_ERROR("Illogical state: " << m_runState); - - default: - CATCH_INTERNAL_ERROR("Unknown state: " << m_runState); - } - moveToParent(); - m_ctx.completeCycle(); -} -void TrackerBase::fail() -{ - m_runState = Failed; - if (m_parent) - m_parent->markAsNeedingAnotherRun(); - moveToParent(); - m_ctx.completeCycle(); -} -void TrackerBase::markAsNeedingAnotherRun() { m_runState = NeedsAnotherRun; } - -void TrackerBase::moveToParent() -{ - assert(m_parent); - m_ctx.setCurrentTracker(m_parent); -} -void TrackerBase::moveToThis() { m_ctx.setCurrentTracker(this); } - -SectionTracker::SectionTracker(NameAndLocation const &nameAndLocation, - TrackerContext &ctx, ITracker *parent) - : TrackerBase(nameAndLocation, ctx, parent) - , m_trimmed_name(trim(nameAndLocation.name)) -{ - if (parent) { - while (!parent->isSectionTracker()) - parent = &parent->parent(); - - SectionTracker &parentSection = static_cast(*parent); - addNextFilters(parentSection.m_filters); - } -} - -bool SectionTracker::isComplete() const -{ - bool complete = true; - - if (m_filters.empty() || m_filters[0] == "" || - std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != - m_filters.end()) { - complete = TrackerBase::isComplete(); - } - return complete; -} - -bool SectionTracker::isSectionTracker() const { return true; } - -SectionTracker &SectionTracker::acquire( - TrackerContext &ctx, NameAndLocation const &nameAndLocation) -{ - std::shared_ptr section; - - ITracker ¤tTracker = ctx.currentTracker(); - if (ITrackerPtr childTracker = currentTracker.findChild(nameAndLocation)) { - assert(childTracker); - assert(childTracker->isSectionTracker()); - section = std::static_pointer_cast(childTracker); - } - else { - section = std::make_shared( - nameAndLocation, ctx, ¤tTracker); - currentTracker.addChild(section); - } - if (!ctx.completedCycle()) - section->tryOpen(); - return *section; -} - -void SectionTracker::tryOpen() -{ - if (!isComplete()) - open(); -} - -void SectionTracker::addInitialFilters(std::vector const &filters) -{ - if (!filters.empty()) { - m_filters.reserve(m_filters.size() + filters.size() + 2); - m_filters.emplace_back(""); // Root - should never be consulted - m_filters.emplace_back(""); // Test Case - not a section filter - m_filters.insert(m_filters.end(), filters.begin(), filters.end()); - } -} -void SectionTracker::addNextFilters(std::vector const &filters) -{ - if (filters.size() > 1) - m_filters.insert(m_filters.end(), filters.begin() + 1, filters.end()); -} - -std::vector const &SectionTracker::getFilters() const -{ - return m_filters; -} - -std::string const &SectionTracker::trimmedName() const -{ - return m_trimmed_name; -} - -} // namespace TestCaseTracking - -using TestCaseTracking::ITracker; -using TestCaseTracking::SectionTracker; -using TestCaseTracking::TrackerContext; - -} // namespace Catch - -#if defined(__clang__) -#pragma clang diagnostic pop -#endif -// end catch_test_case_tracker.cpp -// start catch_test_registry.cpp - -namespace Catch { - -auto makeTestInvoker(void (*testAsFunction)()) noexcept -> ITestInvoker * -{ - return new (std::nothrow) TestInvokerAsFunction(testAsFunction); -} - -NameAndTags::NameAndTags( - StringRef const &name_, StringRef const &tags_) noexcept - : name(name_) - , tags(tags_) -{ -} - -AutoReg::AutoReg(ITestInvoker *invoker, SourceLineInfo const &lineInfo, - StringRef const &classOrMethod, NameAndTags const &nameAndTags) noexcept -{ - CATCH_TRY - { - getMutableRegistryHub().registerTest(makeTestCase( - invoker, extractClassName(classOrMethod), nameAndTags, lineInfo)); - } - CATCH_CATCH_ALL - { - // Do not throw when constructing global objects, instead register the - // exception to be processed later - getMutableRegistryHub().registerStartupException(); - } -} - -AutoReg::~AutoReg() = default; -} -// end catch_test_registry.cpp -// start catch_test_spec.cpp - -#include -#include -#include -#include - -namespace Catch { - -TestSpec::Pattern::Pattern(std::string const &name) - : m_name(name) -{ -} - -TestSpec::Pattern::~Pattern() = default; - -std::string const &TestSpec::Pattern::name() const { return m_name; } - -TestSpec::NamePattern::NamePattern( - std::string const &name, std::string const &filterString) - : Pattern(filterString) - , m_wildcardPattern(toLower(name), CaseSensitive::No) -{ -} - -bool TestSpec::NamePattern::matches(TestCaseInfo const &testCase) const -{ - return m_wildcardPattern.matches(testCase.name); -} - -TestSpec::TagPattern::TagPattern( - std::string const &tag, std::string const &filterString) - : Pattern(filterString) - , m_tag(toLower(tag)) -{ -} - -bool TestSpec::TagPattern::matches(TestCaseInfo const &testCase) const -{ - return std::find(begin(testCase.lcaseTags), end(testCase.lcaseTags), - m_tag) != end(testCase.lcaseTags); -} - -TestSpec::ExcludedPattern::ExcludedPattern(PatternPtr const &underlyingPattern) - : Pattern(underlyingPattern->name()) - , m_underlyingPattern(underlyingPattern) -{ -} - -bool TestSpec::ExcludedPattern::matches(TestCaseInfo const &testCase) const -{ - return !m_underlyingPattern->matches(testCase); -} - -bool TestSpec::Filter::matches(TestCaseInfo const &testCase) const -{ - return std::all_of(m_patterns.begin(), m_patterns.end(), - [&](PatternPtr const &p) { return p->matches(testCase); }); -} - -std::string TestSpec::Filter::name() const -{ - std::string name; - for (auto const &p : m_patterns) - name += p->name(); - return name; -} - -bool TestSpec::hasFilters() const { return !m_filters.empty(); } - -bool TestSpec::matches(TestCaseInfo const &testCase) const -{ - return std::any_of(m_filters.begin(), m_filters.end(), - [&](Filter const &f) { return f.matches(testCase); }); -} - -TestSpec::Matches TestSpec::matchesByFilter( - std::vector const &testCases, IConfig const &config) const -{ - Matches matches(m_filters.size()); - std::transform(m_filters.begin(), m_filters.end(), matches.begin(), - [&](Filter const &filter) { - std::vector currentMatches; - for (auto const &test : testCases) - if (isThrowSafe(test, config) && filter.matches(test)) - currentMatches.emplace_back(&test); - return FilterMatch{filter.name(), currentMatches}; - }); - return matches; -} - -const TestSpec::vectorStrings &TestSpec::getInvalidArgs() const -{ - return (m_invalidArgs); -} - -} -// end catch_test_spec.cpp -// start catch_test_spec_parser.cpp - -namespace Catch { - -TestSpecParser::TestSpecParser(ITagAliasRegistry const &tagAliases) - : m_tagAliases(&tagAliases) -{ -} - -TestSpecParser &TestSpecParser::parse(std::string const &arg) -{ - m_mode = None; - m_exclusion = false; - m_arg = m_tagAliases->expandAliases(arg); - m_escapeChars.clear(); - m_substring.reserve(m_arg.size()); - m_patternName.reserve(m_arg.size()); - m_realPatternPos = 0; - - for (m_pos = 0; m_pos < m_arg.size(); ++m_pos) - // if visitChar fails - if (!visitChar(m_arg[m_pos])) { - m_testSpec.m_invalidArgs.push_back(arg); - break; - } - endMode(); - return *this; -} -TestSpec TestSpecParser::testSpec() -{ - addFilter(); - return m_testSpec; -} -bool TestSpecParser::visitChar(char c) -{ - if ((m_mode != EscapedName) && (c == '\\')) { - escape(); - addCharToPattern(c); - return true; - } - else if ((m_mode != EscapedName) && (c == ',')) { - return separate(); - } - - switch (m_mode) { - case None: - if (processNoneChar(c)) - return true; - break; - case Name: - processNameChar(c); - break; - case EscapedName: - endMode(); - addCharToPattern(c); - return true; - default: - case Tag: - case QuotedName: - if (processOtherChar(c)) - return true; - break; - } - - m_substring += c; - if (!isControlChar(c)) { - m_patternName += c; - m_realPatternPos++; - } - return true; -} -// Two of the processing methods return true to signal the caller to return -// without adding the given character to the current pattern strings -bool TestSpecParser::processNoneChar(char c) -{ - switch (c) { - case ' ': - return true; - case '~': - m_exclusion = true; - return false; - case '[': - startNewMode(Tag); - return false; - case '"': - startNewMode(QuotedName); - return false; - default: - startNewMode(Name); - return false; - } -} -void TestSpecParser::processNameChar(char c) -{ - if (c == '[') { - if (m_substring == "exclude:") - m_exclusion = true; - else - endMode(); - startNewMode(Tag); - } -} -bool TestSpecParser::processOtherChar(char c) -{ - if (!isControlChar(c)) - return false; - m_substring += c; - endMode(); - return true; -} -void TestSpecParser::startNewMode(Mode mode) { m_mode = mode; } -void TestSpecParser::endMode() -{ - switch (m_mode) { - case Name: - case QuotedName: - return addNamePattern(); - case Tag: - return addTagPattern(); - case EscapedName: - revertBackToLastMode(); - return; - case None: - default: - return startNewMode(None); - } -} -void TestSpecParser::escape() -{ - saveLastMode(); - m_mode = EscapedName; - m_escapeChars.push_back(m_realPatternPos); -} -bool TestSpecParser::isControlChar(char c) const -{ - switch (m_mode) { - default: - return false; - case None: - return c == '~'; - case Name: - return c == '['; - case EscapedName: - return true; - case QuotedName: - return c == '"'; - case Tag: - return c == '[' || c == ']'; - } -} - -void TestSpecParser::addFilter() -{ - if (!m_currentFilter.m_patterns.empty()) { - m_testSpec.m_filters.push_back(m_currentFilter); - m_currentFilter = TestSpec::Filter(); - } -} - -void TestSpecParser::saveLastMode() { lastMode = m_mode; } - -void TestSpecParser::revertBackToLastMode() { m_mode = lastMode; } - -bool TestSpecParser::separate() -{ - if ((m_mode == QuotedName) || (m_mode == Tag)) { - // invalid argument, signal failure to previous scope. - m_mode = None; - m_pos = m_arg.size(); - m_substring.clear(); - m_patternName.clear(); - m_realPatternPos = 0; - return false; - } - endMode(); - addFilter(); - return true; // success -} - -std::string TestSpecParser::preprocessPattern() -{ - std::string token = m_patternName; - for (std::size_t i = 0; i < m_escapeChars.size(); ++i) - token = token.substr(0, m_escapeChars[i] - i) + - token.substr(m_escapeChars[i] - i + 1); - m_escapeChars.clear(); - if (startsWith(token, "exclude:")) { - m_exclusion = true; - token = token.substr(8); - } - - m_patternName.clear(); - m_realPatternPos = 0; - - return token; -} - -void TestSpecParser::addNamePattern() -{ - auto token = preprocessPattern(); - - if (!token.empty()) { - TestSpec::PatternPtr pattern = - std::make_shared(token, m_substring); - if (m_exclusion) - pattern = std::make_shared(pattern); - m_currentFilter.m_patterns.push_back(pattern); - } - m_substring.clear(); - m_exclusion = false; - m_mode = None; -} - -void TestSpecParser::addTagPattern() -{ - auto token = preprocessPattern(); - - if (!token.empty()) { - // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo]) - // we have to create a separate hide tag and shorten the real one - if (token.size() > 1 && token[0] == '.') { - token.erase(token.begin()); - TestSpec::PatternPtr pattern = - std::make_shared(".", m_substring); - if (m_exclusion) { - pattern = std::make_shared(pattern); - } - m_currentFilter.m_patterns.push_back(pattern); - } - - TestSpec::PatternPtr pattern = - std::make_shared(token, m_substring); - - if (m_exclusion) { - pattern = std::make_shared(pattern); - } - m_currentFilter.m_patterns.push_back(pattern); - } - m_substring.clear(); - m_exclusion = false; - m_mode = None; -} - -TestSpec parseTestSpec(std::string const &arg) -{ - return TestSpecParser(ITagAliasRegistry::get()).parse(arg).testSpec(); -} - -} // namespace Catch -// end catch_test_spec_parser.cpp -// start catch_timer.cpp - -#include - -static const uint64_t nanosecondsInSecond = 1000000000; - -namespace Catch { - -auto getCurrentNanosecondsSinceEpoch() -> uint64_t -{ - return std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()) - .count(); -} - -namespace { -auto estimateClockResolution() -> uint64_t -{ - uint64_t sum = 0; - static const uint64_t iterations = 1000000; - - auto startTime = getCurrentNanosecondsSinceEpoch(); - - for (std::size_t i = 0; i < iterations; ++i) { - - uint64_t ticks; - uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); - do { - ticks = getCurrentNanosecondsSinceEpoch(); - } while (ticks == baseTicks); - - auto delta = ticks - baseTicks; - sum += delta; - - // If we have been calibrating for over 3 seconds -- the clock - // is terrible and we should move on. - // TBD: How to signal that the measured resolution is probably wrong? - if (ticks > startTime + 3 * nanosecondsInSecond) { - return sum / (i + 1u); - } - } - - // We're just taking the mean, here. To do better we could take the std. dev - // and exclude outliers - // - and potentially do more iterations if there's a high variance. - return sum / iterations; -} -} -auto getEstimatedClockResolution() -> uint64_t -{ - static auto s_resolution = estimateClockResolution(); - return s_resolution; -} - -void Timer::start() { m_nanoseconds = getCurrentNanosecondsSinceEpoch(); } -auto Timer::getElapsedNanoseconds() const -> uint64_t -{ - return getCurrentNanosecondsSinceEpoch() - m_nanoseconds; -} -auto Timer::getElapsedMicroseconds() const -> uint64_t -{ - return getElapsedNanoseconds() / 1000; -} -auto Timer::getElapsedMilliseconds() const -> unsigned int -{ - return static_cast(getElapsedMicroseconds() / 1000); -} -auto Timer::getElapsedSeconds() const -> double -{ - return getElapsedMicroseconds() / 1000000.0; -} - -} // namespace Catch -// end catch_timer.cpp -// start catch_tostring.cpp - -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wexit-time-destructors" -#pragma clang diagnostic ignored "-Wglobal-constructors" -#endif - -// Enable specific decls locally -#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -#endif - -#include -#include - -namespace Catch { - -namespace Detail { - -const std::string unprintableString = "{?}"; - -namespace { -const int hexThreshold = 255; - -struct Endianness { - enum Arch { Big, Little }; - - static Arch which() - { - int one = 1; - // If the lowest byte we read is non-zero, we can assume - // that little endian format is used. - auto value = *reinterpret_cast(&one); - return value ? Little : Big; - } -}; -} - -std::string rawMemoryToString(const void *object, std::size_t size) -{ - // Reverse order for little endian architectures - int i = 0, end = static_cast(size), inc = 1; - if (Endianness::which() == Endianness::Little) { - i = end - 1; - end = inc = -1; - } - - unsigned char const *bytes = static_cast(object); - ReusableStringStream rss; - rss << "0x" << std::setfill('0') << std::hex; - for (; i != end; i += inc) - rss << std::setw(2) << static_cast(bytes[i]); - return rss.str(); -} -} - -template std::string fpToString(T value, int precision) -{ - if (Catch::isnan(value)) { - return "nan"; - } - - ReusableStringStream rss; - rss << std::setprecision(precision) << std::fixed << value; - std::string d = rss.str(); - std::size_t i = d.find_last_not_of('0'); - if (i != std::string::npos && i != d.size() - 1) { - if (d[i] == '.') - i++; - d = d.substr(0, i + 1); - } - return d; -} - -//// ======================================================= //// -// -// Out-of-line defs for full specialization of StringMaker -// -//// ======================================================= //// - -std::string StringMaker::convert(const std::string &str) -{ - if (!getCurrentContext().getConfig()->showInvisibles()) { - return '"' + str + '"'; - } - - std::string s("\""); - for (char c : str) { - switch (c) { - case '\n': - s.append("\\n"); - break; - case '\t': - s.append("\\t"); - break; - default: - s.push_back(c); - break; - } - } - s.append("\""); - return s; -} - -#ifdef CATCH_CONFIG_CPP17_STRING_VIEW -std::string StringMaker::convert(std::string_view str) -{ - return ::Catch::Detail::stringify(std::string{str}); -} -#endif - -std::string StringMaker::convert(char const *str) -{ - if (str) { - return ::Catch::Detail::stringify(std::string{str}); - } - else { - return {"{null string}"}; - } -} -std::string StringMaker::convert(char *str) -{ - if (str) { - return ::Catch::Detail::stringify(std::string{str}); - } - else { - return {"{null string}"}; - } -} - -#ifdef CATCH_CONFIG_WCHAR -std::string StringMaker::convert(const std::wstring &wstr) -{ - std::string s; - s.reserve(wstr.size()); - for (auto c : wstr) { - s += (c <= 0xff) ? static_cast(c) : '?'; - } - return ::Catch::Detail::stringify(s); -} - -#ifdef CATCH_CONFIG_CPP17_STRING_VIEW -std::string StringMaker::convert(std::wstring_view str) -{ - return StringMaker::convert(std::wstring(str)); -} -#endif - -std::string StringMaker::convert(wchar_t const *str) -{ - if (str) { - return ::Catch::Detail::stringify(std::wstring{str}); - } - else { - return {"{null string}"}; - } -} -std::string StringMaker::convert(wchar_t *str) -{ - if (str) { - return ::Catch::Detail::stringify(std::wstring{str}); - } - else { - return {"{null string}"}; - } -} -#endif - -#if defined(CATCH_CONFIG_CPP17_BYTE) -#include -std::string StringMaker::convert(std::byte value) -{ - return ::Catch::Detail::stringify( - std::to_integer(value)); -} -#endif // defined(CATCH_CONFIG_CPP17_BYTE) - -std::string StringMaker::convert(int value) -{ - return ::Catch::Detail::stringify(static_cast(value)); -} -std::string StringMaker::convert(long value) -{ - return ::Catch::Detail::stringify(static_cast(value)); -} -std::string StringMaker::convert(long long value) -{ - ReusableStringStream rss; - rss << value; - if (value > Detail::hexThreshold) { - rss << " (0x" << std::hex << value << ')'; - } - return rss.str(); -} - -std::string StringMaker::convert(unsigned int value) -{ - return ::Catch::Detail::stringify(static_cast(value)); -} -std::string StringMaker::convert(unsigned long value) -{ - return ::Catch::Detail::stringify(static_cast(value)); -} -std::string StringMaker::convert(unsigned long long value) -{ - ReusableStringStream rss; - rss << value; - if (value > Detail::hexThreshold) { - rss << " (0x" << std::hex << value << ')'; - } - return rss.str(); -} - -std::string StringMaker::convert(bool b) { return b ? "true" : "false"; } - -std::string StringMaker::convert(signed char value) -{ - if (value == '\r') { - return "'\\r'"; - } - else if (value == '\f') { - return "'\\f'"; - } - else if (value == '\n') { - return "'\\n'"; - } - else if (value == '\t') { - return "'\\t'"; - } - else if ('\0' <= value && value < ' ') { - return ::Catch::Detail::stringify(static_cast(value)); - } - else { - char chstr[] = "' '"; - chstr[1] = value; - return chstr; - } -} -std::string StringMaker::convert(char c) -{ - return ::Catch::Detail::stringify(static_cast(c)); -} -std::string StringMaker::convert(unsigned char c) -{ - return ::Catch::Detail::stringify(static_cast(c)); -} - -std::string StringMaker::convert(std::nullptr_t) -{ - return "nullptr"; -} - -int StringMaker::precision = 5; - -std::string StringMaker::convert(float value) -{ - return fpToString(value, precision) + 'f'; -} - -int StringMaker::precision = 10; - -std::string StringMaker::convert(double value) -{ - return fpToString(value, precision); -} - -std::string ratio_string::symbol() { return "a"; } -std::string ratio_string::symbol() { return "f"; } -std::string ratio_string::symbol() { return "p"; } -std::string ratio_string::symbol() { return "n"; } -std::string ratio_string::symbol() { return "u"; } -std::string ratio_string::symbol() { return "m"; } - -} // end namespace Catch - -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - -// end catch_tostring.cpp -// start catch_totals.cpp - -namespace Catch { - -Counts Counts::operator-(Counts const &other) const -{ - Counts diff; - diff.passed = passed - other.passed; - diff.failed = failed - other.failed; - diff.failedButOk = failedButOk - other.failedButOk; - return diff; -} - -Counts &Counts::operator+=(Counts const &other) -{ - passed += other.passed; - failed += other.failed; - failedButOk += other.failedButOk; - return *this; -} - -std::size_t Counts::total() const { return passed + failed + failedButOk; } -bool Counts::allPassed() const { return failed == 0 && failedButOk == 0; } -bool Counts::allOk() const { return failed == 0; } - -Totals Totals::operator-(Totals const &other) const -{ - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; -} - -Totals &Totals::operator+=(Totals const &other) -{ - assertions += other.assertions; - testCases += other.testCases; - return *this; -} - -Totals Totals::delta(Totals const &prevTotals) const -{ - Totals diff = *this - prevTotals; - if (diff.assertions.failed > 0) - ++diff.testCases.failed; - else if (diff.assertions.failedButOk > 0) - ++diff.testCases.failedButOk; - else - ++diff.testCases.passed; - return diff; -} - -} -// end catch_totals.cpp -// start catch_uncaught_exceptions.cpp - -// start catch_config_uncaught_exceptions.hpp - -// Copyright Catch2 Authors -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// https://www.boost.org/LICENSE_1_0.txt) - -// SPDX-License-Identifier: BSL-1.0 - -#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP -#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP - -#if defined(_MSC_VER) -#if _MSC_VER >= 1900 // Visual Studio 2015 or newer -#define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif -#endif - -#include - -#if defined(__cpp_lib_uncaught_exceptions) && \ - !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) - -#define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif // __cpp_lib_uncaught_exceptions - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && \ - !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && \ - !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) - -#define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - -#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP -// end catch_config_uncaught_exceptions.hpp -#include - -namespace Catch { -bool uncaught_exceptions() -{ -#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - return false; -#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) - return std::uncaught_exceptions() > 0; -#else - return std::uncaught_exception(); -#endif -} -} // end namespace Catch -// end catch_uncaught_exceptions.cpp -// start catch_version.cpp - -#include - -namespace Catch { - -Version::Version(unsigned int _majorVersion, unsigned int _minorVersion, - unsigned int _patchNumber, char const *const _branchName, - unsigned int _buildNumber) - : majorVersion(_majorVersion) - , minorVersion(_minorVersion) - , patchNumber(_patchNumber) - , branchName(_branchName) - , buildNumber(_buildNumber) -{ -} - -std::ostream &operator<<(std::ostream &os, Version const &version) -{ - os << version.majorVersion << '.' << version.minorVersion << '.' - << version.patchNumber; - // branchName is never null -> 0th char is \0 if it is empty - if (version.branchName[0]) { - os << '-' << version.branchName << '.' << version.buildNumber; - } - return os; -} - -Version const &libraryVersion() -{ - static Version version(2, 13, 8, "", 0); - return version; -} - -} -// end catch_version.cpp -// start catch_wildcard_pattern.cpp - -namespace Catch { - -WildcardPattern::WildcardPattern( - std::string const &pattern, CaseSensitive::Choice caseSensitivity) - : m_caseSensitivity(caseSensitivity) - , m_pattern(normaliseString(pattern)) -{ - if (startsWith(m_pattern, '*')) { - m_pattern = m_pattern.substr(1); - m_wildcard = WildcardAtStart; - } - if (endsWith(m_pattern, '*')) { - m_pattern = m_pattern.substr(0, m_pattern.size() - 1); - m_wildcard = static_cast(m_wildcard | WildcardAtEnd); - } -} - -bool WildcardPattern::matches(std::string const &str) const -{ - switch (m_wildcard) { - case NoWildcard: - return m_pattern == normaliseString(str); - case WildcardAtStart: - return endsWith(normaliseString(str), m_pattern); - case WildcardAtEnd: - return startsWith(normaliseString(str), m_pattern); - case WildcardAtBothEnds: - return contains(normaliseString(str), m_pattern); - default: - CATCH_INTERNAL_ERROR("Unknown enum"); - } -} - -std::string WildcardPattern::normaliseString(std::string const &str) const -{ - return trim(m_caseSensitivity == CaseSensitive::No ? toLower(str) : str); -} -} -// end catch_wildcard_pattern.cpp -// start catch_xmlwriter.cpp - -#include -#include - -namespace Catch { - -namespace { - -size_t trailingBytes(unsigned char c) -{ - if ((c & 0xE0) == 0xC0) { - return 2; - } - if ((c & 0xF0) == 0xE0) { - return 3; - } - if ((c & 0xF8) == 0xF0) { - return 4; - } - CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); -} - -uint32_t headerValue(unsigned char c) -{ - if ((c & 0xE0) == 0xC0) { - return c & 0x1F; - } - if ((c & 0xF0) == 0xE0) { - return c & 0x0F; - } - if ((c & 0xF8) == 0xF0) { - return c & 0x07; - } - CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); -} - -void hexEscapeChar(std::ostream &os, unsigned char c) -{ - std::ios_base::fmtflags f(os.flags()); - os << "\\x" << std::uppercase << std::hex << std::setfill('0') - << std::setw(2) << static_cast(c); - os.flags(f); -} - -bool shouldNewline(XmlFormatting fmt) -{ - return !!(static_cast::type>( - fmt & XmlFormatting::Newline)); -} - -bool shouldIndent(XmlFormatting fmt) -{ - return !!(static_cast::type>( - fmt & XmlFormatting::Indent)); -} - -} // anonymous namespace - -XmlFormatting operator|(XmlFormatting lhs, XmlFormatting rhs) -{ - return static_cast( - static_cast::type>(lhs) | - static_cast::type>(rhs)); -} - -XmlFormatting operator&(XmlFormatting lhs, XmlFormatting rhs) -{ - return static_cast( - static_cast::type>(lhs) & - static_cast::type>(rhs)); -} - -XmlEncode::XmlEncode(std::string const &str, ForWhat forWhat) - : m_str(str) - , m_forWhat(forWhat) -{ -} - -void XmlEncode::encodeTo(std::ostream &os) const -{ - // Apostrophe escaping not necessary if we always use " to write attributes - // (see: http://www.w3.org/TR/xml/#syntax) - - for (std::size_t idx = 0; idx < m_str.size(); ++idx) { - unsigned char c = m_str[idx]; - switch (c) { - case '<': - os << "<"; - break; - case '&': - os << "&"; - break; - - case '>': - // See: http://www.w3.org/TR/xml/#syntax - if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') - os << ">"; - else - os << c; - break; - - case '\"': - if (m_forWhat == ForAttributes) - os << """; - else - os << c; - break; - - default: - // Check for control characters and invalid utf-8 - - // Escape control characters in standard ascii - // see - // http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { - hexEscapeChar(os, c); - break; - } - - // Plain ASCII: Write it to stream - if (c < 0x7F) { - os << c; - break; - } - - // UTF-8 territory - // Check if the encoding is valid and if it is not, hex escape - // bytes. Important: We do not check the exact decoded values for - // validity, only the encoding format First check that this bytes is - // a valid lead byte: This means that it is not encoded as 1111 1XXX - // Or as 10XX XXXX - if (c < 0xC0 || c >= 0xF8) { - hexEscapeChar(os, c); - break; - } - - auto encBytes = trailingBytes(c); - // Are there enough bytes left to avoid accessing out-of-bounds - // memory? - if (idx + encBytes - 1 >= m_str.size()) { - hexEscapeChar(os, c); - break; - } - // The header is valid, check data - // The next encBytes bytes must together be a valid utf-8 - // This means: bitpattern 10XX XXXX and the extracted value is sane - // (ish) - bool valid = true; - uint32_t value = headerValue(c); - for (std::size_t n = 1; n < encBytes; ++n) { - unsigned char nc = m_str[idx + n]; - valid &= ((nc & 0xC0) == 0x80); - value = (value << 6) | (nc & 0x3F); - } - - if ( - // Wrong bit pattern of following bytes - (!valid) || - // Overlong encodings - (value < 0x80) || - (0x80 <= value && value < 0x800 && encBytes > 2) || - (0x800 < value && value < 0x10000 && encBytes > 3) || - // Encoded value out of range - (value >= 0x110000)) { - hexEscapeChar(os, c); - break; - } - - // If we got here, this is in fact a valid(ish) utf-8 sequence - for (std::size_t n = 0; n < encBytes; ++n) { - os << m_str[idx + n]; - } - idx += encBytes - 1; - break; - } - } -} - -std::ostream &operator<<(std::ostream &os, XmlEncode const &xmlEncode) -{ - xmlEncode.encodeTo(os); - return os; -} - -XmlWriter::ScopedElement::ScopedElement(XmlWriter *writer, XmlFormatting fmt) - : m_writer(writer) - , m_fmt(fmt) -{ -} - -XmlWriter::ScopedElement::ScopedElement(ScopedElement &&other) noexcept - : m_writer(other.m_writer) - , m_fmt(other.m_fmt) -{ - other.m_writer = nullptr; - other.m_fmt = XmlFormatting::None; -} -XmlWriter::ScopedElement &XmlWriter::ScopedElement::operator=( - ScopedElement &&other) noexcept -{ - if (m_writer) { - m_writer->endElement(); - } - m_writer = other.m_writer; - other.m_writer = nullptr; - m_fmt = other.m_fmt; - other.m_fmt = XmlFormatting::None; - return *this; -} - -XmlWriter::ScopedElement::~ScopedElement() -{ - if (m_writer) { - m_writer->endElement(m_fmt); - } -} - -XmlWriter::ScopedElement &XmlWriter::ScopedElement::writeText( - std::string const &text, XmlFormatting fmt) -{ - m_writer->writeText(text, fmt); - return *this; -} - -XmlWriter::XmlWriter(std::ostream &os) - : m_os(os) -{ - writeDeclaration(); -} - -XmlWriter::~XmlWriter() -{ - while (!m_tags.empty()) { - endElement(); - } - newlineIfNecessary(); -} - -XmlWriter &XmlWriter::startElement(std::string const &name, XmlFormatting fmt) -{ - ensureTagClosed(); - newlineIfNecessary(); - if (shouldIndent(fmt)) { - m_os << m_indent; - m_indent += " "; - } - m_os << '<' << name; - m_tags.push_back(name); - m_tagIsOpen = true; - applyFormatting(fmt); - return *this; -} - -XmlWriter::ScopedElement XmlWriter::scopedElement( - std::string const &name, XmlFormatting fmt) -{ - ScopedElement scoped(this, fmt); - startElement(name, fmt); - return scoped; -} - -XmlWriter &XmlWriter::endElement(XmlFormatting fmt) -{ - m_indent = m_indent.substr(0, m_indent.size() - 2); - - if (m_tagIsOpen) { - m_os << "/>"; - m_tagIsOpen = false; - } - else { - newlineIfNecessary(); - if (shouldIndent(fmt)) { - m_os << m_indent; - } - m_os << ""; - } - m_os << std::flush; - applyFormatting(fmt); - m_tags.pop_back(); - return *this; -} - -XmlWriter &XmlWriter::writeAttribute( - std::string const &name, std::string const &attribute) -{ - if (!name.empty() && !attribute.empty()) - m_os << ' ' << name << "=\"" - << XmlEncode(attribute, XmlEncode::ForAttributes) << '"'; - return *this; -} - -XmlWriter &XmlWriter::writeAttribute(std::string const &name, bool attribute) -{ - m_os << ' ' << name << "=\"" << (attribute ? "true" : "false") << '"'; - return *this; -} - -XmlWriter &XmlWriter::writeText(std::string const &text, XmlFormatting fmt) -{ - if (!text.empty()) { - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if (tagWasOpen && shouldIndent(fmt)) { - m_os << m_indent; - } - m_os << XmlEncode(text); - applyFormatting(fmt); - } - return *this; -} - -XmlWriter &XmlWriter::writeComment(std::string const &text, XmlFormatting fmt) -{ - ensureTagClosed(); - if (shouldIndent(fmt)) { - m_os << m_indent; - } - m_os << ""; - applyFormatting(fmt); - return *this; -} - -void XmlWriter::writeStylesheetRef(std::string const &url) -{ - m_os << "\n"; -} - -XmlWriter &XmlWriter::writeBlankLine() -{ - ensureTagClosed(); - m_os << '\n'; - return *this; -} - -void XmlWriter::ensureTagClosed() -{ - if (m_tagIsOpen) { - m_os << '>' << std::flush; - newlineIfNecessary(); - m_tagIsOpen = false; - } -} - -void XmlWriter::applyFormatting(XmlFormatting fmt) -{ - m_needsNewline = shouldNewline(fmt); -} - -void XmlWriter::writeDeclaration() -{ - m_os << "\n"; -} - -void XmlWriter::newlineIfNecessary() -{ - if (m_needsNewline) { - m_os << std::endl; - m_needsNewline = false; - } -} -} -// end catch_xmlwriter.cpp -// start catch_reporter_bases.cpp - -#include -#include -#include -#include -#include - -namespace Catch { -void prepareExpandedExpression(AssertionResult &result) -{ - result.getExpandedExpression(); -} - -// Because formatting using c++ streams is stateful, drop down to C is required -// Alternatively we could use stringstream, but its performance is... not good. -std::string getFormattedDuration(double duration) -{ - // Max exponent + 1 is required to represent the whole part - // + 1 for decimal point - // + 3 for the 3 decimal places - // + 1 for null terminator - const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; - char buffer[maxDoubleSize]; - - // Save previous errno, to prevent sprintf from overwriting it - ErrnoGuard guard; -#ifdef _MSC_VER - sprintf_s(buffer, "%.3f", duration); -#else - std::sprintf(buffer, "%.3f", duration); -#endif - return std::string(buffer); -} - -bool shouldShowDuration(IConfig const &config, double duration) -{ - if (config.showDurations() == ShowDurations::Always) { - return true; - } - if (config.showDurations() == ShowDurations::Never) { - return false; - } - const double min = config.minDuration(); - return min >= 0 && duration >= min; -} - -std::string serializeFilters(std::vector const &container) -{ - ReusableStringStream oss; - bool first = true; - for (auto &&filter : container) { - if (!first) - oss << ' '; - else - first = false; - - oss << filter; - } - return oss.str(); -} - -TestEventListenerBase::TestEventListenerBase(ReporterConfig const &_config) - : StreamingReporterBase(_config) -{ -} - -std::set TestEventListenerBase::getSupportedVerbosities() -{ - return {Verbosity::Quiet, Verbosity::Normal, Verbosity::High}; -} - -void TestEventListenerBase::assertionStarting(AssertionInfo const &) { } - -bool TestEventListenerBase::assertionEnded(AssertionStats const &) -{ - return false; -} - -} // end namespace Catch -// end catch_reporter_bases.cpp -// start catch_reporter_compact.cpp - -namespace { - -#ifdef CATCH_PLATFORM_MAC -const char *failedString() { return "FAILED"; } -const char *passedString() { return "PASSED"; } -#else -const char *failedString() { return "failed"; } -const char *passedString() { return "passed"; } -#endif - -// Colour::LightGrey -Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } - -std::string bothOrAll(std::size_t count) -{ - return count == 1 ? std::string() : count == 2 ? "both " : "all "; -} - -} // anon namespace - -namespace Catch { -namespace { -// Colour, message variants: -// - white: No tests ran. -// - red: Failed [both/all] N test cases, failed [both/all] M assertions. -// - white: Passed [both/all] N test cases (no assertions). -// - red: Failed N tests cases, failed M assertions. -// - green: Passed [both/all] N tests cases with M assertions. -void printTotals(std::ostream &out, const Totals &totals) -{ - if (totals.testCases.total() == 0) { - out << "No tests ran."; - } - else if (totals.testCases.failed == totals.testCases.total()) { - Colour colour(Colour::ResultError); - const std::string qualify_assertions_failed = - totals.assertions.failed == totals.assertions.total() - ? bothOrAll(totals.assertions.failed) - : std::string(); - out << "Failed " << bothOrAll(totals.testCases.failed) - << pluralise(totals.testCases.failed, "test case") - << ", " - "failed " - << qualify_assertions_failed - << pluralise(totals.assertions.failed, "assertion") << '.'; - } - else if (totals.assertions.total() == 0) { - out << "Passed " << bothOrAll(totals.testCases.total()) - << pluralise(totals.testCases.total(), "test case") - << " (no assertions)."; - } - else if (totals.assertions.failed) { - Colour colour(Colour::ResultError); - out << "Failed " << pluralise(totals.testCases.failed, "test case") - << ", " - "failed " - << pluralise(totals.assertions.failed, "assertion") << '.'; - } - else { - Colour colour(Colour::ResultSuccess); - out << "Passed " << bothOrAll(totals.testCases.passed) - << pluralise(totals.testCases.passed, "test case") << " with " - << pluralise(totals.assertions.passed, "assertion") << '.'; - } -} - -// Implementation of CompactReporter formatting -class AssertionPrinter { -public: - AssertionPrinter &operator=(AssertionPrinter const &) = delete; - AssertionPrinter(AssertionPrinter const &) = delete; - AssertionPrinter(std::ostream &_stream, AssertionStats const &_stats, - bool _printInfoMessages) - : stream(_stream) - , result(_stats.assertionResult) - , messages(_stats.infoMessages) - , itMessage(_stats.infoMessages.begin()) - , printInfoMessages(_printInfoMessages) - { - } - - void print() - { - printSourceInfo(); - - itMessage = messages.begin(); - - switch (result.getResultType()) { - case ResultWas::Ok: - printResultType(Colour::ResultSuccess, passedString()); - printOriginalExpression(); - printReconstructedExpression(); - if (!result.hasExpression()) - printRemainingMessages(Colour::None); - else - printRemainingMessages(); - break; - case ResultWas::ExpressionFailed: - if (result.isOk()) - printResultType(Colour::ResultSuccess, - failedString() + std::string(" - but was ok")); - else - printResultType(Colour::Error, failedString()); - printOriginalExpression(); - printReconstructedExpression(); - printRemainingMessages(); - break; - case ResultWas::ThrewException: - printResultType(Colour::Error, failedString()); - printIssue("unexpected exception with message:"); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::FatalErrorCondition: - printResultType(Colour::Error, failedString()); - printIssue("fatal error condition with message:"); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::DidntThrowException: - printResultType(Colour::Error, failedString()); - printIssue("expected exception, got none"); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::Info: - printResultType(Colour::None, "info"); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::Warning: - printResultType(Colour::None, "warning"); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::ExplicitFailure: - printResultType(Colour::Error, failedString()); - printIssue("explicitly"); - printRemainingMessages(Colour::None); - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - printResultType(Colour::Error, "** internal error **"); - break; - } - } - -private: - void printSourceInfo() const - { - Colour colourGuard(Colour::FileName); - stream << result.getSourceInfo() << ':'; - } - - void printResultType( - Colour::Code colour, std::string const &passOrFail) const - { - if (!passOrFail.empty()) { - { - Colour colourGuard(colour); - stream << ' ' << passOrFail; - } - stream << ':'; - } - } - - void printIssue(std::string const &issue) const { stream << ' ' << issue; } - - void printExpressionWas() - { - if (result.hasExpression()) { - stream << ';'; - { - Colour colour(dimColour()); - stream << " expression was:"; - } - printOriginalExpression(); - } - } - - void printOriginalExpression() const - { - if (result.hasExpression()) { - stream << ' ' << result.getExpression(); - } - } - - void printReconstructedExpression() const - { - if (result.hasExpandedExpression()) { - { - Colour colour(dimColour()); - stream << " for: "; - } - stream << result.getExpandedExpression(); - } - } - - void printMessage() - { - if (itMessage != messages.end()) { - stream << " '" << itMessage->message << '\''; - ++itMessage; - } - } - - void printRemainingMessages(Colour::Code colour = dimColour()) - { - if (itMessage == messages.end()) - return; - - const auto itEnd = messages.cend(); - const auto N = - static_cast(std::distance(itMessage, itEnd)); - - { - Colour colourGuard(colour); - stream << " with " << pluralise(N, "message") << ':'; - } - - while (itMessage != itEnd) { - // If this assertion is a warning ignore any INFO messages - if (printInfoMessages || itMessage->type != ResultWas::Info) { - printMessage(); - if (itMessage != itEnd) { - Colour colourGuard(dimColour()); - stream << " and"; - } - continue; - } - ++itMessage; - } - } - -private: - std::ostream &stream; - AssertionResult const &result; - std::vector messages; - std::vector::const_iterator itMessage; - bool printInfoMessages; -}; - -} // anon namespace - -std::string CompactReporter::getDescription() -{ - return "Reports test results on a single line, suitable for IDEs"; -} - -void CompactReporter::noMatchingTestCases(std::string const &spec) -{ - stream << "No test cases matched '" << spec << '\'' << std::endl; -} - -void CompactReporter::assertionStarting(AssertionInfo const &) { } - -bool CompactReporter::assertionEnded(AssertionStats const &_assertionStats) -{ - AssertionResult const &result = _assertionStats.assertionResult; - - bool printInfoMessages = true; - - // Drop out if result was successful and we're not printing those - if (!m_config->includeSuccessfulResults() && result.isOk()) { - if (result.getResultType() != ResultWas::Warning) - return false; - printInfoMessages = false; - } - - AssertionPrinter printer(stream, _assertionStats, printInfoMessages); - printer.print(); - - stream << std::endl; - return true; -} - -void CompactReporter::sectionEnded(SectionStats const &_sectionStats) -{ - double dur = _sectionStats.durationInSeconds; - if (shouldShowDuration(*m_config, dur)) { - stream << getFormattedDuration(dur) - << " s: " << _sectionStats.sectionInfo.name << std::endl; - } -} - -void CompactReporter::testRunEnded(TestRunStats const &_testRunStats) -{ - printTotals(stream, _testRunStats.totals); - stream << '\n' << std::endl; - StreamingReporterBase::testRunEnded(_testRunStats); -} - -CompactReporter::~CompactReporter() { } - -CATCH_REGISTER_REPORTER("compact", CompactReporter) - -} // end namespace Catch -// end catch_reporter_compact.cpp -// start catch_reporter_console.cpp - -#include -#include - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning( \ - disable : 4061) // Not all labels are EXPLICITLY handled in switch - // Note that 4062 (not all labels are handled and default is missing) is - // enabled -#endif - -#if defined(__clang__) -#pragma clang diagnostic push -// For simplicity, benchmarking-only helpers are always enabled -#pragma clang diagnostic ignored "-Wunused-function" -#endif - -namespace Catch { - -namespace { - -// Formatter impl for ConsoleReporter -class ConsoleAssertionPrinter { -public: - ConsoleAssertionPrinter &operator=( - ConsoleAssertionPrinter const &) = delete; - ConsoleAssertionPrinter(ConsoleAssertionPrinter const &) = delete; - ConsoleAssertionPrinter(std::ostream &_stream, AssertionStats const &_stats, - bool _printInfoMessages) - : stream(_stream) - , stats(_stats) - , result(_stats.assertionResult) - , colour(Colour::None) - , message(result.getMessage()) - , messages(_stats.infoMessages) - , printInfoMessages(_printInfoMessages) - { - switch (result.getResultType()) { - case ResultWas::Ok: - colour = Colour::Success; - passOrFail = "PASSED"; - // if( result.hasMessage() ) - if (_stats.infoMessages.size() == 1) - messageLabel = "with message"; - if (_stats.infoMessages.size() > 1) - messageLabel = "with messages"; - break; - case ResultWas::ExpressionFailed: - if (result.isOk()) { - colour = Colour::Success; - passOrFail = "FAILED - but was ok"; - } - else { - colour = Colour::Error; - passOrFail = "FAILED"; - } - if (_stats.infoMessages.size() == 1) - messageLabel = "with message"; - if (_stats.infoMessages.size() > 1) - messageLabel = "with messages"; - break; - case ResultWas::ThrewException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to unexpected exception with "; - if (_stats.infoMessages.size() == 1) - messageLabel += "message"; - if (_stats.infoMessages.size() > 1) - messageLabel += "messages"; - break; - case ResultWas::FatalErrorCondition: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to a fatal error condition"; - break; - case ResultWas::DidntThrowException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = - "because no exception was thrown where one was expected"; - break; - case ResultWas::Info: - messageLabel = "info"; - break; - case ResultWas::Warning: - messageLabel = "warning"; - break; - case ResultWas::ExplicitFailure: - passOrFail = "FAILED"; - colour = Colour::Error; - if (_stats.infoMessages.size() == 1) - messageLabel = "explicitly with message"; - if (_stats.infoMessages.size() > 1) - messageLabel = "explicitly with messages"; - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - passOrFail = "** internal error **"; - colour = Colour::Error; - break; - } - } - - void print() const - { - printSourceInfo(); - if (stats.totals.assertions.total() > 0) { - printResultType(); - printOriginalExpression(); - printReconstructedExpression(); - } - else { - stream << '\n'; - } - printMessage(); - } - -private: - void printResultType() const - { - if (!passOrFail.empty()) { - Colour colourGuard(colour); - stream << passOrFail << ":\n"; - } - } - void printOriginalExpression() const - { - if (result.hasExpression()) { - Colour colourGuard(Colour::OriginalExpression); - stream << " "; - stream << result.getExpressionInMacro(); - stream << '\n'; - } - } - void printReconstructedExpression() const - { - if (result.hasExpandedExpression()) { - stream << "with expansion:\n"; - Colour colourGuard(Colour::ReconstructedExpression); - stream << Column(result.getExpandedExpression()).indent(2) << '\n'; - } - } - void printMessage() const - { - if (!messageLabel.empty()) - stream << messageLabel << ':' << '\n'; - for (auto const &msg : messages) { - // If this assertion is a warning ignore any INFO messages - if (printInfoMessages || msg.type != ResultWas::Info) - stream << Column(msg.message).indent(2) << '\n'; - } - } - void printSourceInfo() const - { - Colour colourGuard(Colour::FileName); - stream << result.getSourceInfo() << ": "; - } - - std::ostream &stream; - AssertionStats const &stats; - AssertionResult const &result; - Colour::Code colour; - std::string passOrFail; - std::string messageLabel; - std::string message; - std::vector messages; - bool printInfoMessages; -}; - -std::size_t makeRatio(std::size_t number, std::size_t total) -{ - std::size_t ratio = - total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0; - return (ratio == 0 && number > 0) ? 1 : ratio; -} - -std::size_t &findMax(std::size_t &i, std::size_t &j, std::size_t &k) -{ - if (i > j && i > k) - return i; - else if (j > k) - return j; - else - return k; -} - -struct ColumnInfo { - enum Justification { Left, Right }; - std::string name; - int width; - Justification justification; -}; -struct ColumnBreak { }; -struct RowBreak { }; - -class Duration { - enum class Unit { - Auto, - Nanoseconds, - Microseconds, - Milliseconds, - Seconds, - Minutes - }; - static const uint64_t s_nanosecondsInAMicrosecond = 1000; - static const uint64_t s_nanosecondsInAMillisecond = - 1000 * s_nanosecondsInAMicrosecond; - static const uint64_t s_nanosecondsInASecond = - 1000 * s_nanosecondsInAMillisecond; - static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; - - double m_inNanoseconds; - Unit m_units; - -public: - explicit Duration(double inNanoseconds, Unit units = Unit::Auto) - : m_inNanoseconds(inNanoseconds) - , m_units(units) - { - if (m_units == Unit::Auto) { - if (m_inNanoseconds < s_nanosecondsInAMicrosecond) - m_units = Unit::Nanoseconds; - else if (m_inNanoseconds < s_nanosecondsInAMillisecond) - m_units = Unit::Microseconds; - else if (m_inNanoseconds < s_nanosecondsInASecond) - m_units = Unit::Milliseconds; - else if (m_inNanoseconds < s_nanosecondsInAMinute) - m_units = Unit::Seconds; - else - m_units = Unit::Minutes; - } - } - - auto value() const -> double - { - switch (m_units) { - case Unit::Microseconds: - return m_inNanoseconds / - static_cast(s_nanosecondsInAMicrosecond); - case Unit::Milliseconds: - return m_inNanoseconds / - static_cast(s_nanosecondsInAMillisecond); - case Unit::Seconds: - return m_inNanoseconds / - static_cast(s_nanosecondsInASecond); - case Unit::Minutes: - return m_inNanoseconds / - static_cast(s_nanosecondsInAMinute); - default: - return m_inNanoseconds; - } - } - auto unitsAsString() const -> std::string - { - switch (m_units) { - case Unit::Nanoseconds: - return "ns"; - case Unit::Microseconds: - return "us"; - case Unit::Milliseconds: - return "ms"; - case Unit::Seconds: - return "s"; - case Unit::Minutes: - return "m"; - default: - return "** internal error **"; - } - } - friend auto operator<<(std::ostream &os, Duration const &duration) - -> std::ostream & - { - return os << duration.value() << ' ' << duration.unitsAsString(); - } -}; -} // end anon namespace - -class TablePrinter { - std::ostream &m_os; - std::vector m_columnInfos; - std::ostringstream m_oss; - int m_currentColumn = -1; - bool m_isOpen = false; - -public: - TablePrinter(std::ostream &os, std::vector columnInfos) - : m_os(os) - , m_columnInfos(std::move(columnInfos)) - { - } - - auto columnInfos() const -> std::vector const & - { - return m_columnInfos; - } - - void open() - { - if (!m_isOpen) { - m_isOpen = true; - *this << RowBreak(); - - Columns headerCols; - Spacer spacer(2); - for (auto const &info : m_columnInfos) { - headerCols += Column(info.name).width( - static_cast(info.width - 2)); - headerCols += spacer; - } - m_os << headerCols << '\n'; - - m_os << Catch::getLineOfChars<'-'>() << '\n'; - } - } - void close() - { - if (m_isOpen) { - *this << RowBreak(); - m_os << std::endl; - m_isOpen = false; - } - } - - template - friend TablePrinter &operator<<(TablePrinter &tp, T const &value) - { - tp.m_oss << value; - return tp; - } - - friend TablePrinter &operator<<(TablePrinter &tp, ColumnBreak) - { - auto colStr = tp.m_oss.str(); - const auto strSize = colStr.size(); - tp.m_oss.str(""); - tp.open(); - if (tp.m_currentColumn == - static_cast(tp.m_columnInfos.size() - 1)) { - tp.m_currentColumn = -1; - tp.m_os << '\n'; - } - tp.m_currentColumn++; - - auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; - auto padding = (strSize + 1 < static_cast(colInfo.width)) - ? std::string(colInfo.width - (strSize + 1), ' ') - : std::string(); - if (colInfo.justification == ColumnInfo::Left) - tp.m_os << colStr << padding << ' '; - else - tp.m_os << padding << colStr << ' '; - return tp; - } - - friend TablePrinter &operator<<(TablePrinter &tp, RowBreak) - { - if (tp.m_currentColumn > 0) { - tp.m_os << '\n'; - tp.m_currentColumn = -1; - } - return tp; - } -}; - -ConsoleReporter::ConsoleReporter(ReporterConfig const &config) - : StreamingReporterBase(config) - , m_tablePrinter(new TablePrinter( - config.stream(), [&config]() -> std::vector { - if (config.fullConfig()->benchmarkNoAnalysis()) { - return {{"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, - ColumnInfo::Left}, - {" samples", 14, ColumnInfo::Right}, - {" iterations", 14, ColumnInfo::Right}, - {" mean", 14, ColumnInfo::Right}}; - } - else { - return {{"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, - ColumnInfo::Left}, - {"samples mean std dev", 14, - ColumnInfo::Right}, - {"iterations low mean low std dev", 14, - ColumnInfo::Right}, - {"estimated high mean high std dev", 14, - ColumnInfo::Right}}; - } - }())) -{ -} -ConsoleReporter::~ConsoleReporter() = default; - -std::string ConsoleReporter::getDescription() -{ - return "Reports test results as plain lines of text"; -} - -void ConsoleReporter::noMatchingTestCases(std::string const &spec) -{ - stream << "No test cases matched '" << spec << '\'' << std::endl; -} - -void ConsoleReporter::reportInvalidArguments(std::string const &arg) -{ - stream << "Invalid Filter: " << arg << std::endl; -} - -void ConsoleReporter::assertionStarting(AssertionInfo const &) { } - -bool ConsoleReporter::assertionEnded(AssertionStats const &_assertionStats) -{ - AssertionResult const &result = _assertionStats.assertionResult; - - bool includeResults = - m_config->includeSuccessfulResults() || !result.isOk(); - - // Drop out if result was successful but we're not printing them. - if (!includeResults && result.getResultType() != ResultWas::Warning) - return false; - - lazyPrint(); - - ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults); - printer.print(); - stream << std::endl; - return true; -} - -void ConsoleReporter::sectionStarting(SectionInfo const &_sectionInfo) -{ - m_tablePrinter->close(); - m_headerPrinted = false; - StreamingReporterBase::sectionStarting(_sectionInfo); -} -void ConsoleReporter::sectionEnded(SectionStats const &_sectionStats) -{ - m_tablePrinter->close(); - if (_sectionStats.missingAssertions) { - lazyPrint(); - Colour colour(Colour::ResultError); - if (m_sectionStack.size() > 1) - stream << "\nNo assertions in section"; - else - stream << "\nNo assertions in test case"; - stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; - } - double dur = _sectionStats.durationInSeconds; - if (shouldShowDuration(*m_config, dur)) { - stream << getFormattedDuration(dur) - << " s: " << _sectionStats.sectionInfo.name << std::endl; - } - if (m_headerPrinted) { - m_headerPrinted = false; - } - StreamingReporterBase::sectionEnded(_sectionStats); -} - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -void ConsoleReporter::benchmarkPreparing(std::string const &name) -{ - lazyPrintWithoutClosingBenchmarkTable(); - - auto nameCol = Column(name).width( - static_cast(m_tablePrinter->columnInfos()[0].width - 2)); - - bool firstLine = true; - for (auto line : nameCol) { - if (!firstLine) - (*m_tablePrinter) - << ColumnBreak() << ColumnBreak() << ColumnBreak(); - else - firstLine = false; - - (*m_tablePrinter) << line << ColumnBreak(); - } -} - -void ConsoleReporter::benchmarkStarting(BenchmarkInfo const &info) -{ - (*m_tablePrinter) << info.samples << ColumnBreak() << info.iterations - << ColumnBreak(); - if (!m_config->benchmarkNoAnalysis()) - (*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak(); -} -void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const &stats) -{ - if (m_config->benchmarkNoAnalysis()) { - (*m_tablePrinter) << Duration(stats.mean.point.count()) - << ColumnBreak(); - } - else { - (*m_tablePrinter) - << ColumnBreak() << Duration(stats.mean.point.count()) - << ColumnBreak() << Duration(stats.mean.lower_bound.count()) - << ColumnBreak() << Duration(stats.mean.upper_bound.count()) - << ColumnBreak() << ColumnBreak() - << Duration(stats.standardDeviation.point.count()) << ColumnBreak() - << Duration(stats.standardDeviation.lower_bound.count()) - << ColumnBreak() - << Duration(stats.standardDeviation.upper_bound.count()) - << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() - << ColumnBreak(); - } -} - -void ConsoleReporter::benchmarkFailed(std::string const &error) -{ - Colour colour(Colour::Red); - (*m_tablePrinter) << "Benchmark failed (" << error << ')' << ColumnBreak() - << RowBreak(); -} -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - -void ConsoleReporter::testCaseEnded(TestCaseStats const &_testCaseStats) -{ - m_tablePrinter->close(); - StreamingReporterBase::testCaseEnded(_testCaseStats); - m_headerPrinted = false; -} -void ConsoleReporter::testGroupEnded(TestGroupStats const &_testGroupStats) -{ - if (currentGroupInfo.used) { - printSummaryDivider(); - stream << "Summary for group '" << _testGroupStats.groupInfo.name - << "':\n"; - printTotals(_testGroupStats.totals); - stream << '\n' << std::endl; - } - StreamingReporterBase::testGroupEnded(_testGroupStats); -} -void ConsoleReporter::testRunEnded(TestRunStats const &_testRunStats) -{ - printTotalsDivider(_testRunStats.totals); - printTotals(_testRunStats.totals); - stream << std::endl; - StreamingReporterBase::testRunEnded(_testRunStats); -} -void ConsoleReporter::testRunStarting(TestRunInfo const &_testInfo) -{ - StreamingReporterBase::testRunStarting(_testInfo); - printTestFilters(); -} - -void ConsoleReporter::lazyPrint() -{ - - m_tablePrinter->close(); - lazyPrintWithoutClosingBenchmarkTable(); -} - -void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() -{ - - if (!currentTestRunInfo.used) - lazyPrintRunInfo(); - if (!currentGroupInfo.used) - lazyPrintGroupInfo(); - - if (!m_headerPrinted) { - printTestCaseAndSectionHeader(); - m_headerPrinted = true; - } -} -void ConsoleReporter::lazyPrintRunInfo() -{ - stream << '\n' << getLineOfChars<'~'>() << '\n'; - Colour colour(Colour::SecondaryText); - stream << currentTestRunInfo->name << " is a Catch v" << libraryVersion() - << " host application.\n" - << "Run with -? for options\n\n"; - - if (m_config->rngSeed() != 0) - stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; - - currentTestRunInfo.used = true; -} -void ConsoleReporter::lazyPrintGroupInfo() -{ - if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) { - printClosedHeader("Group: " + currentGroupInfo->name); - currentGroupInfo.used = true; - } -} -void ConsoleReporter::printTestCaseAndSectionHeader() -{ - assert(!m_sectionStack.empty()); - printOpenHeader(currentTestCaseInfo->name); - - if (m_sectionStack.size() > 1) { - Colour colourGuard(Colour::Headers); - - auto it = m_sectionStack.begin() + 1, // Skip first section (test case) - itEnd = m_sectionStack.end(); - for (; it != itEnd; ++it) - printHeaderString(it->name, 2); - } - - SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; - - stream << getLineOfChars<'-'>() << '\n'; - Colour colourGuard(Colour::FileName); - stream << lineInfo << '\n'; - stream << getLineOfChars<'.'>() << '\n' << std::endl; -} - -void ConsoleReporter::printClosedHeader(std::string const &_name) -{ - printOpenHeader(_name); - stream << getLineOfChars<'.'>() << '\n'; -} -void ConsoleReporter::printOpenHeader(std::string const &_name) -{ - stream << getLineOfChars<'-'>() << '\n'; - { - Colour colourGuard(Colour::Headers); - printHeaderString(_name); - } -} - -// if string has a : in first line will set indent to follow it on -// subsequent lines -void ConsoleReporter::printHeaderString( - std::string const &_string, std::size_t indent) -{ - std::size_t i = _string.find(": "); - if (i != std::string::npos) - i += 2; - else - i = 0; - stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n'; -} - -struct SummaryColumn { - - SummaryColumn(std::string _label, Colour::Code _colour) - : label(std::move(_label)) - , colour(_colour) - { - } - SummaryColumn addRow(std::size_t count) - { - ReusableStringStream rss; - rss << count; - std::string row = rss.str(); - for (auto &oldRow : rows) { - while (oldRow.size() < row.size()) - oldRow = ' ' + oldRow; - while (oldRow.size() > row.size()) - row = ' ' + row; - } - rows.push_back(row); - return *this; - } - - std::string label; - Colour::Code colour; - std::vector rows; -}; - -void ConsoleReporter::printTotals(Totals const &totals) -{ - if (totals.testCases.total() == 0) { - stream << Colour(Colour::Warning) << "No tests ran\n"; - } - else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) { - stream << Colour(Colour::ResultSuccess) << "All tests passed"; - stream << " (" << pluralise(totals.assertions.passed, "assertion") - << " in " << pluralise(totals.testCases.passed, "test case") - << ')' << '\n'; - } - else { - - std::vector columns; - columns.push_back(SummaryColumn("", Colour::None) - .addRow(totals.testCases.total()) - .addRow(totals.assertions.total())); - columns.push_back(SummaryColumn("passed", Colour::Success) - .addRow(totals.testCases.passed) - .addRow(totals.assertions.passed)); - columns.push_back(SummaryColumn("failed", Colour::ResultError) - .addRow(totals.testCases.failed) - .addRow(totals.assertions.failed)); - columns.push_back( - SummaryColumn("failed as expected", Colour::ResultExpectedFailure) - .addRow(totals.testCases.failedButOk) - .addRow(totals.assertions.failedButOk)); - - printSummaryRow("test cases", columns, 0); - printSummaryRow("assertions", columns, 1); - } -} -void ConsoleReporter::printSummaryRow(std::string const &label, - std::vector const &cols, std::size_t row) -{ - for (auto col : cols) { - std::string value = col.rows[row]; - if (col.label.empty()) { - stream << label << ": "; - if (value != "0") - stream << value; - else - stream << Colour(Colour::Warning) << "- none -"; - } - else if (value != "0") { - stream << Colour(Colour::LightGrey) << " | "; - stream << Colour(col.colour) << value << ' ' << col.label; - } - } - stream << '\n'; -} - -void ConsoleReporter::printTotalsDivider(Totals const &totals) -{ - if (totals.testCases.total() > 0) { - std::size_t failedRatio = - makeRatio(totals.testCases.failed, totals.testCases.total()); - std::size_t failedButOkRatio = - makeRatio(totals.testCases.failedButOk, totals.testCases.total()); - std::size_t passedRatio = - makeRatio(totals.testCases.passed, totals.testCases.total()); - while (failedRatio + failedButOkRatio + passedRatio < - CATCH_CONFIG_CONSOLE_WIDTH - 1) - findMax(failedRatio, failedButOkRatio, passedRatio)++; - while (failedRatio + failedButOkRatio + passedRatio > - CATCH_CONFIG_CONSOLE_WIDTH - 1) - findMax(failedRatio, failedButOkRatio, passedRatio)--; - - stream << Colour(Colour::Error) << std::string(failedRatio, '='); - stream << Colour(Colour::ResultExpectedFailure) - << std::string(failedButOkRatio, '='); - if (totals.testCases.allPassed()) - stream << Colour(Colour::ResultSuccess) - << std::string(passedRatio, '='); - else - stream << Colour(Colour::Success) << std::string(passedRatio, '='); - } - else { - stream << Colour(Colour::Warning) - << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '='); - } - stream << '\n'; -} -void ConsoleReporter::printSummaryDivider() -{ - stream << getLineOfChars<'-'>() << '\n'; -} - -void ConsoleReporter::printTestFilters() -{ - if (m_config->testSpec().hasFilters()) { - Colour guard(Colour::BrightYellow); - stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) - << '\n'; - } -} - -CATCH_REGISTER_REPORTER("console", ConsoleReporter) - -} // end namespace Catch - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -#if defined(__clang__) -#pragma clang diagnostic pop -#endif -// end catch_reporter_console.cpp -// start catch_reporter_junit.cpp - -#include -#include -#include -#include -#include - -namespace Catch { - -namespace { -std::string getCurrentTimestamp() -{ - // Beware, this is not reentrant because of backward compatibility issues - // Also, UTC only, again because of backward compatibility (%z is C++11) - time_t rawtime; - std::time(&rawtime); - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - -#ifdef _MSC_VER - std::tm timeInfo = {}; - gmtime_s(&timeInfo, &rawtime); -#else - std::tm *timeInfo; - timeInfo = std::gmtime(&rawtime); -#endif - - char timeStamp[timeStampSize]; - const char *const fmt = "%Y-%m-%dT%H:%M:%SZ"; - -#ifdef _MSC_VER - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); -#else - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); -#endif - return std::string(timeStamp, timeStampSize - 1); -} - -std::string fileNameTag(const std::vector &tags) -{ - auto it = std::find_if(begin(tags), end(tags), - [](std::string const &tag) { return tag.front() == '#'; }); - if (it != tags.end()) - return it->substr(1); - return std::string(); -} - -// Formats the duration in seconds to 3 decimal places. -// This is done because some genius defined Maven Surefire schema -// in a way that only accepts 3 decimal places, and tools like -// Jenkins use that schema for validation JUnit reporter output. -std::string formatDuration(double seconds) -{ - ReusableStringStream rss; - rss << std::fixed << std::setprecision(3) << seconds; - return rss.str(); -} - -} // anonymous namespace - -JunitReporter::JunitReporter(ReporterConfig const &_config) - : CumulativeReporterBase(_config) - , xml(_config.stream()) -{ - m_reporterPrefs.shouldRedirectStdOut = true; - m_reporterPrefs.shouldReportAllAssertions = true; -} - -JunitReporter::~JunitReporter() { } - -std::string JunitReporter::getDescription() -{ - return "Reports test results in an XML format that looks like Ant's " - "junitreport target"; -} - -void JunitReporter::noMatchingTestCases(std::string const & /*spec*/) { } - -void JunitReporter::testRunStarting(TestRunInfo const &runInfo) -{ - CumulativeReporterBase::testRunStarting(runInfo); - xml.startElement("testsuites"); -} - -void JunitReporter::testGroupStarting(GroupInfo const &groupInfo) -{ - suiteTimer.start(); - stdOutForSuite.clear(); - stdErrForSuite.clear(); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting(groupInfo); -} - -void JunitReporter::testCaseStarting(TestCaseInfo const &testCaseInfo) -{ - m_okToFail = testCaseInfo.okToFail(); -} - -bool JunitReporter::assertionEnded(AssertionStats const &assertionStats) -{ - if (assertionStats.assertionResult.getResultType() == - ResultWas::ThrewException && - !m_okToFail) - unexpectedExceptions++; - return CumulativeReporterBase::assertionEnded(assertionStats); -} - -void JunitReporter::testCaseEnded(TestCaseStats const &testCaseStats) -{ - stdOutForSuite += testCaseStats.stdOut; - stdErrForSuite += testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded(testCaseStats); -} - -void JunitReporter::testGroupEnded(TestGroupStats const &testGroupStats) -{ - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded(testGroupStats); - writeGroup(*m_testGroups.back(), suiteTime); -} - -void JunitReporter::testRunEndedCumulative() { xml.endElement(); } - -void JunitReporter::writeGroup(TestGroupNode const &groupNode, double suiteTime) -{ - XmlWriter::ScopedElement e = xml.scopedElement("testsuite"); - - TestGroupStats const &stats = groupNode.value; - xml.writeAttribute("name", stats.groupInfo.name); - xml.writeAttribute("errors", unexpectedExceptions); - xml.writeAttribute( - "failures", stats.totals.assertions.failed - unexpectedExceptions); - xml.writeAttribute("tests", stats.totals.assertions.total()); - xml.writeAttribute("hostname", "tbd"); // !TBD - if (m_config->showDurations() == ShowDurations::Never) - xml.writeAttribute("time", ""); - else - xml.writeAttribute("time", formatDuration(suiteTime)); - xml.writeAttribute("timestamp", getCurrentTimestamp()); - - // Write properties if there are any - if (m_config->hasTestFilters() || m_config->rngSeed() != 0) { - auto properties = xml.scopedElement("properties"); - if (m_config->hasTestFilters()) { - xml.scopedElement("property") - .writeAttribute("name", "filters") - .writeAttribute( - "value", serializeFilters(m_config->getTestsOrTags())); - } - if (m_config->rngSeed() != 0) { - xml.scopedElement("property") - .writeAttribute("name", "random-seed") - .writeAttribute("value", m_config->rngSeed()); - } - } - - // Write test cases - for (auto const &child : groupNode.children) - writeTestCase(*child); - - xml.scopedElement("system-out") - .writeText(trim(stdOutForSuite), XmlFormatting::Newline); - xml.scopedElement("system-err") - .writeText(trim(stdErrForSuite), XmlFormatting::Newline); -} - -void JunitReporter::writeTestCase(TestCaseNode const &testCaseNode) -{ - TestCaseStats const &stats = testCaseNode.value; - - // All test cases have exactly one section - which represents the - // test case itself. That section may have 0-n nested sections - assert(testCaseNode.children.size() == 1); - SectionNode const &rootSection = *testCaseNode.children.front(); - - std::string className = stats.testInfo.className; - - if (className.empty()) { - className = fileNameTag(stats.testInfo.tags); - if (className.empty()) - className = "global"; - } - - if (!m_config->name().empty()) - className = m_config->name() + "." + className; - - writeSection(className, "", rootSection, stats.testInfo.okToFail()); -} - -void JunitReporter::writeSection(std::string const &className, - std::string const &rootName, SectionNode const §ionNode, - bool testOkToFail) -{ - std::string name = trim(sectionNode.stats.sectionInfo.name); - if (!rootName.empty()) - name = rootName + '/' + name; - - if (!sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || - !sectionNode.stdErr.empty()) { - XmlWriter::ScopedElement e = xml.scopedElement("testcase"); - if (className.empty()) { - xml.writeAttribute("classname", name); - xml.writeAttribute("name", "root"); - } - else { - xml.writeAttribute("classname", className); - xml.writeAttribute("name", name); - } - xml.writeAttribute( - "time", formatDuration(sectionNode.stats.durationInSeconds)); - // This is not ideal, but it should be enough to mimic gtest's - // junit output. - // Ideally the JUnit reporter would also handle `skipTest` - // events and write those out appropriately. - xml.writeAttribute("status", "run"); - - if (sectionNode.stats.assertions.failedButOk) { - xml.scopedElement("skipped").writeAttribute( - "message", "TEST_CASE tagged with !mayfail"); - } - - writeAssertions(sectionNode); - - if (!sectionNode.stdOut.empty()) - xml.scopedElement("system-out") - .writeText(trim(sectionNode.stdOut), XmlFormatting::Newline); - if (!sectionNode.stdErr.empty()) - xml.scopedElement("system-err") - .writeText(trim(sectionNode.stdErr), XmlFormatting::Newline); - } - for (auto const &childNode : sectionNode.childSections) - if (className.empty()) - writeSection(name, "", *childNode, testOkToFail); - else - writeSection(className, name, *childNode, testOkToFail); -} - -void JunitReporter::writeAssertions(SectionNode const §ionNode) -{ - for (auto const &assertion : sectionNode.assertions) - writeAssertion(assertion); -} - -void JunitReporter::writeAssertion(AssertionStats const &stats) -{ - AssertionResult const &result = stats.assertionResult; - if (!result.isOk()) { - std::string elementName; - switch (result.getResultType()) { - case ResultWas::ThrewException: - case ResultWas::FatalErrorCondition: - elementName = "error"; - break; - case ResultWas::ExplicitFailure: - case ResultWas::ExpressionFailed: - case ResultWas::DidntThrowException: - elementName = "failure"; - break; - - // We should never see these here: - case ResultWas::Info: - case ResultWas::Warning: - case ResultWas::Ok: - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - elementName = "internalError"; - break; - } - - XmlWriter::ScopedElement e = xml.scopedElement(elementName); - - xml.writeAttribute("message", result.getExpression()); - xml.writeAttribute("type", result.getTestMacroName()); - - ReusableStringStream rss; - if (stats.totals.assertions.total() > 0) { - rss << "FAILED" - << ":\n"; - if (result.hasExpression()) { - rss << " "; - rss << result.getExpressionInMacro(); - rss << '\n'; - } - if (result.hasExpandedExpression()) { - rss << "with expansion:\n"; - rss << Column(result.getExpandedExpression()).indent(2) << '\n'; - } - } - else { - rss << '\n'; - } - - if (!result.getMessage().empty()) - rss << result.getMessage() << '\n'; - for (auto const &msg : stats.infoMessages) - if (msg.type == ResultWas::Info) - rss << msg.message << '\n'; - - rss << "at " << result.getSourceInfo(); - xml.writeText(rss.str(), XmlFormatting::Newline); - } -} - -CATCH_REGISTER_REPORTER("junit", JunitReporter) - -} // end namespace Catch -// end catch_reporter_junit.cpp -// start catch_reporter_listening.cpp - -#include - -namespace Catch { - -ListeningReporter::ListeningReporter() -{ - // We will assume that listeners will always want all assertions - m_preferences.shouldReportAllAssertions = true; -} - -void ListeningReporter::addListener(IStreamingReporterPtr &&listener) -{ - m_listeners.push_back(std::move(listener)); -} - -void ListeningReporter::addReporter(IStreamingReporterPtr &&reporter) -{ - assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); - m_reporter = std::move(reporter); - m_preferences.shouldRedirectStdOut = - m_reporter->getPreferences().shouldRedirectStdOut; -} - -ReporterPreferences ListeningReporter::getPreferences() const -{ - return m_preferences; -} - -std::set ListeningReporter::getSupportedVerbosities() -{ - return std::set{}; -} - -void ListeningReporter::noMatchingTestCases(std::string const &spec) -{ - for (auto const &listener : m_listeners) { - listener->noMatchingTestCases(spec); - } - m_reporter->noMatchingTestCases(spec); -} - -void ListeningReporter::reportInvalidArguments(std::string const &arg) -{ - for (auto const &listener : m_listeners) { - listener->reportInvalidArguments(arg); - } - m_reporter->reportInvalidArguments(arg); -} - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -void ListeningReporter::benchmarkPreparing(std::string const &name) -{ - for (auto const &listener : m_listeners) { - listener->benchmarkPreparing(name); - } - m_reporter->benchmarkPreparing(name); -} -void ListeningReporter::benchmarkStarting(BenchmarkInfo const &benchmarkInfo) -{ - for (auto const &listener : m_listeners) { - listener->benchmarkStarting(benchmarkInfo); - } - m_reporter->benchmarkStarting(benchmarkInfo); -} -void ListeningReporter::benchmarkEnded(BenchmarkStats<> const &benchmarkStats) -{ - for (auto const &listener : m_listeners) { - listener->benchmarkEnded(benchmarkStats); - } - m_reporter->benchmarkEnded(benchmarkStats); -} - -void ListeningReporter::benchmarkFailed(std::string const &error) -{ - for (auto const &listener : m_listeners) { - listener->benchmarkFailed(error); - } - m_reporter->benchmarkFailed(error); -} -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - -void ListeningReporter::testRunStarting(TestRunInfo const &testRunInfo) -{ - for (auto const &listener : m_listeners) { - listener->testRunStarting(testRunInfo); - } - m_reporter->testRunStarting(testRunInfo); -} - -void ListeningReporter::testGroupStarting(GroupInfo const &groupInfo) -{ - for (auto const &listener : m_listeners) { - listener->testGroupStarting(groupInfo); - } - m_reporter->testGroupStarting(groupInfo); -} - -void ListeningReporter::testCaseStarting(TestCaseInfo const &testInfo) -{ - for (auto const &listener : m_listeners) { - listener->testCaseStarting(testInfo); - } - m_reporter->testCaseStarting(testInfo); -} - -void ListeningReporter::sectionStarting(SectionInfo const §ionInfo) -{ - for (auto const &listener : m_listeners) { - listener->sectionStarting(sectionInfo); - } - m_reporter->sectionStarting(sectionInfo); -} - -void ListeningReporter::assertionStarting(AssertionInfo const &assertionInfo) -{ - for (auto const &listener : m_listeners) { - listener->assertionStarting(assertionInfo); - } - m_reporter->assertionStarting(assertionInfo); -} - -// The return value indicates if the messages buffer should be cleared: -bool ListeningReporter::assertionEnded(AssertionStats const &assertionStats) -{ - for (auto const &listener : m_listeners) { - static_cast(listener->assertionEnded(assertionStats)); - } - return m_reporter->assertionEnded(assertionStats); -} - -void ListeningReporter::sectionEnded(SectionStats const §ionStats) -{ - for (auto const &listener : m_listeners) { - listener->sectionEnded(sectionStats); - } - m_reporter->sectionEnded(sectionStats); -} - -void ListeningReporter::testCaseEnded(TestCaseStats const &testCaseStats) -{ - for (auto const &listener : m_listeners) { - listener->testCaseEnded(testCaseStats); - } - m_reporter->testCaseEnded(testCaseStats); -} - -void ListeningReporter::testGroupEnded(TestGroupStats const &testGroupStats) -{ - for (auto const &listener : m_listeners) { - listener->testGroupEnded(testGroupStats); - } - m_reporter->testGroupEnded(testGroupStats); -} - -void ListeningReporter::testRunEnded(TestRunStats const &testRunStats) -{ - for (auto const &listener : m_listeners) { - listener->testRunEnded(testRunStats); - } - m_reporter->testRunEnded(testRunStats); -} - -void ListeningReporter::skipTest(TestCaseInfo const &testInfo) -{ - for (auto const &listener : m_listeners) { - listener->skipTest(testInfo); - } - m_reporter->skipTest(testInfo); -} - -bool ListeningReporter::isMulti() const { return true; } - -} // end namespace Catch -// end catch_reporter_listening.cpp -// start catch_reporter_xml.cpp - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4061) // Not all labels are EXPLICITLY handled in - // switch Note that 4062 (not all labels are - // handled and default is missing) is enabled -#endif - -namespace Catch { -XmlReporter::XmlReporter(ReporterConfig const &_config) - : StreamingReporterBase(_config) - , m_xml(_config.stream()) -{ - m_reporterPrefs.shouldRedirectStdOut = true; - m_reporterPrefs.shouldReportAllAssertions = true; -} - -XmlReporter::~XmlReporter() = default; - -std::string XmlReporter::getDescription() -{ - return "Reports test results as an XML document"; -} - -std::string XmlReporter::getStylesheetRef() const { return std::string(); } - -void XmlReporter::writeSourceInfo(SourceLineInfo const &sourceInfo) -{ - m_xml.writeAttribute("filename", sourceInfo.file) - .writeAttribute("line", sourceInfo.line); -} - -void XmlReporter::noMatchingTestCases(std::string const &s) -{ - StreamingReporterBase::noMatchingTestCases(s); -} - -void XmlReporter::testRunStarting(TestRunInfo const &testInfo) -{ - StreamingReporterBase::testRunStarting(testInfo); - std::string stylesheetRef = getStylesheetRef(); - if (!stylesheetRef.empty()) - m_xml.writeStylesheetRef(stylesheetRef); - m_xml.startElement("Catch"); - if (!m_config->name().empty()) - m_xml.writeAttribute("name", m_config->name()); - if (m_config->testSpec().hasFilters()) - m_xml.writeAttribute( - "filters", serializeFilters(m_config->getTestsOrTags())); - if (m_config->rngSeed() != 0) - m_xml.scopedElement("Randomness") - .writeAttribute("seed", m_config->rngSeed()); -} - -void XmlReporter::testGroupStarting(GroupInfo const &groupInfo) -{ - StreamingReporterBase::testGroupStarting(groupInfo); - m_xml.startElement("Group").writeAttribute("name", groupInfo.name); -} - -void XmlReporter::testCaseStarting(TestCaseInfo const &testInfo) -{ - StreamingReporterBase::testCaseStarting(testInfo); - m_xml.startElement("TestCase") - .writeAttribute("name", trim(testInfo.name)) - .writeAttribute("description", testInfo.description) - .writeAttribute("tags", testInfo.tagsAsString()); - - writeSourceInfo(testInfo.lineInfo); - - if (m_config->showDurations() == ShowDurations::Always) - m_testCaseTimer.start(); - m_xml.ensureTagClosed(); -} - -void XmlReporter::sectionStarting(SectionInfo const §ionInfo) -{ - StreamingReporterBase::sectionStarting(sectionInfo); - if (m_sectionDepth++ > 0) { - m_xml.startElement("Section").writeAttribute( - "name", trim(sectionInfo.name)); - writeSourceInfo(sectionInfo.lineInfo); - m_xml.ensureTagClosed(); - } -} - -void XmlReporter::assertionStarting(AssertionInfo const &) { } - -bool XmlReporter::assertionEnded(AssertionStats const &assertionStats) -{ - - AssertionResult const &result = assertionStats.assertionResult; - - bool includeResults = - m_config->includeSuccessfulResults() || !result.isOk(); - - if (includeResults || result.getResultType() == ResultWas::Warning) { - // Print any info messages in tags. - for (auto const &msg : assertionStats.infoMessages) { - if (msg.type == ResultWas::Info && includeResults) { - m_xml.scopedElement("Info").writeText(msg.message); - } - else if (msg.type == ResultWas::Warning) { - m_xml.scopedElement("Warning").writeText(msg.message); - } - } - } - - // Drop out if result was successful but we're not printing them. - if (!includeResults && result.getResultType() != ResultWas::Warning) - return true; - - // Print the expression if there is one. - if (result.hasExpression()) { - m_xml.startElement("Expression") - .writeAttribute("success", result.succeeded()) - .writeAttribute("type", result.getTestMacroName()); - - writeSourceInfo(result.getSourceInfo()); - - m_xml.scopedElement("Original").writeText(result.getExpression()); - m_xml.scopedElement("Expanded") - .writeText(result.getExpandedExpression()); - } - - // And... Print a result applicable to each result type. - switch (result.getResultType()) { - case ResultWas::ThrewException: - m_xml.startElement("Exception"); - writeSourceInfo(result.getSourceInfo()); - m_xml.writeText(result.getMessage()); - m_xml.endElement(); - break; - case ResultWas::FatalErrorCondition: - m_xml.startElement("FatalErrorCondition"); - writeSourceInfo(result.getSourceInfo()); - m_xml.writeText(result.getMessage()); - m_xml.endElement(); - break; - case ResultWas::Info: - m_xml.scopedElement("Info").writeText(result.getMessage()); - break; - case ResultWas::Warning: - // Warning will already have been written - break; - case ResultWas::ExplicitFailure: - m_xml.startElement("Failure"); - writeSourceInfo(result.getSourceInfo()); - m_xml.writeText(result.getMessage()); - m_xml.endElement(); - break; - default: - break; - } - - if (result.hasExpression()) - m_xml.endElement(); - - return true; -} - -void XmlReporter::sectionEnded(SectionStats const §ionStats) -{ - StreamingReporterBase::sectionEnded(sectionStats); - if (--m_sectionDepth > 0) { - XmlWriter::ScopedElement e = m_xml.scopedElement("OverallResults"); - e.writeAttribute("successes", sectionStats.assertions.passed); - e.writeAttribute("failures", sectionStats.assertions.failed); - e.writeAttribute( - "expectedFailures", sectionStats.assertions.failedButOk); - - if (m_config->showDurations() == ShowDurations::Always) - e.writeAttribute( - "durationInSeconds", sectionStats.durationInSeconds); - - m_xml.endElement(); - } -} - -void XmlReporter::testCaseEnded(TestCaseStats const &testCaseStats) -{ - StreamingReporterBase::testCaseEnded(testCaseStats); - XmlWriter::ScopedElement e = m_xml.scopedElement("OverallResult"); - e.writeAttribute("success", testCaseStats.totals.assertions.allOk()); - - if (m_config->showDurations() == ShowDurations::Always) - e.writeAttribute( - "durationInSeconds", m_testCaseTimer.getElapsedSeconds()); - - if (!testCaseStats.stdOut.empty()) - m_xml.scopedElement("StdOut").writeText( - trim(testCaseStats.stdOut), XmlFormatting::Newline); - if (!testCaseStats.stdErr.empty()) - m_xml.scopedElement("StdErr").writeText( - trim(testCaseStats.stdErr), XmlFormatting::Newline); - - m_xml.endElement(); -} - -void XmlReporter::testGroupEnded(TestGroupStats const &testGroupStats) -{ - StreamingReporterBase::testGroupEnded(testGroupStats); - // TODO: Check testGroupStats.aborting and act accordingly. - m_xml.scopedElement("OverallResults") - .writeAttribute("successes", testGroupStats.totals.assertions.passed) - .writeAttribute("failures", testGroupStats.totals.assertions.failed) - .writeAttribute( - "expectedFailures", testGroupStats.totals.assertions.failedButOk); - m_xml.scopedElement("OverallResultsCases") - .writeAttribute("successes", testGroupStats.totals.testCases.passed) - .writeAttribute("failures", testGroupStats.totals.testCases.failed) - .writeAttribute( - "expectedFailures", testGroupStats.totals.testCases.failedButOk); - m_xml.endElement(); -} - -void XmlReporter::testRunEnded(TestRunStats const &testRunStats) -{ - StreamingReporterBase::testRunEnded(testRunStats); - m_xml.scopedElement("OverallResults") - .writeAttribute("successes", testRunStats.totals.assertions.passed) - .writeAttribute("failures", testRunStats.totals.assertions.failed) - .writeAttribute( - "expectedFailures", testRunStats.totals.assertions.failedButOk); - m_xml.scopedElement("OverallResultsCases") - .writeAttribute("successes", testRunStats.totals.testCases.passed) - .writeAttribute("failures", testRunStats.totals.testCases.failed) - .writeAttribute( - "expectedFailures", testRunStats.totals.testCases.failedButOk); - m_xml.endElement(); -} - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -void XmlReporter::benchmarkPreparing(std::string const &name) -{ - m_xml.startElement("BenchmarkResults").writeAttribute("name", name); -} - -void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) -{ - m_xml.writeAttribute("samples", info.samples) - .writeAttribute("resamples", info.resamples) - .writeAttribute("iterations", info.iterations) - .writeAttribute("clockResolution", info.clockResolution) - .writeAttribute("estimatedDuration", info.estimatedDuration) - .writeComment("All values in nano seconds"); -} - -void XmlReporter::benchmarkEnded(BenchmarkStats<> const &benchmarkStats) -{ - m_xml.startElement("mean") - .writeAttribute("value", benchmarkStats.mean.point.count()) - .writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count()) - .writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count()) - .writeAttribute("ci", benchmarkStats.mean.confidence_interval); - m_xml.endElement(); - m_xml.startElement("standardDeviation") - .writeAttribute("value", benchmarkStats.standardDeviation.point.count()) - .writeAttribute( - "lowerBound", benchmarkStats.standardDeviation.lower_bound.count()) - .writeAttribute( - "upperBound", benchmarkStats.standardDeviation.upper_bound.count()) - .writeAttribute( - "ci", benchmarkStats.standardDeviation.confidence_interval); - m_xml.endElement(); - m_xml.startElement("outliers") - .writeAttribute("variance", benchmarkStats.outlierVariance) - .writeAttribute("lowMild", benchmarkStats.outliers.low_mild) - .writeAttribute("lowSevere", benchmarkStats.outliers.low_severe) - .writeAttribute("highMild", benchmarkStats.outliers.high_mild) - .writeAttribute("highSevere", benchmarkStats.outliers.high_severe); - m_xml.endElement(); - m_xml.endElement(); -} - -void XmlReporter::benchmarkFailed(std::string const &error) -{ - m_xml.scopedElement("failed").writeAttribute("message", error); - m_xml.endElement(); -} -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - -CATCH_REGISTER_REPORTER("xml", XmlReporter) - -} // end namespace Catch - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif -// end catch_reporter_xml.cpp - -namespace Catch { -LeakDetector leakDetector; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// end catch_impl.hpp -#endif - -#ifdef CATCH_CONFIG_MAIN -// start catch_default_main.hpp - -#ifndef __OBJC__ - -#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && \ - defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) -// Standard C/C++ Win32 Unicode wmain entry point -extern "C" int wmain(int argc, wchar_t *argv[], wchar_t *[]) -{ -#else -// Standard C/C++ main entry point -int main(int argc, char *argv[]) -{ -#endif - - return Catch::Session().run(argc, argv); -} - -#else // __OBJC__ - -// Objective-C entry point -int main(int argc, char *const argv[]) -{ -#if !CATCH_ARC_ENABLED - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; -#endif - - Catch::registerTestMethods(); - int result = Catch::Session().run(argc, (char **)argv); - -#if !CATCH_ARC_ENABLED - [pool drain]; -#endif - - return result; -} - -#endif // __OBJC__ - -// end catch_default_main.hpp -#endif - -#if !defined(CATCH_CONFIG_IMPL_ONLY) - -#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED -#undef CLARA_CONFIG_MAIN -#endif - -#if !defined(CATCH_CONFIG_DISABLE) -////// -// If this config identifier is defined then all CATCH macros are prefixed with -// CATCH_ -#ifdef CATCH_CONFIG_PREFIX_ALL - -#define CATCH_REQUIRE(...) \ - INTERNAL_CATCH_TEST( \ - "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__) -#define CATCH_REQUIRE_FALSE(...) \ - INTERNAL_CATCH_TEST("CATCH_REQUIRE_FALSE", \ - Catch::ResultDisposition::Normal | \ - Catch::ResultDisposition::FalseTest, \ - __VA_ARGS__) - -#define CATCH_REQUIRE_THROWS(...) \ - INTERNAL_CATCH_THROWS( \ - "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__) -#define CATCH_REQUIRE_THROWS_AS(expr, exceptionType) \ - INTERNAL_CATCH_THROWS_AS("CATCH_REQUIRE_THROWS_AS", exceptionType, \ - Catch::ResultDisposition::Normal, expr) -#define CATCH_REQUIRE_THROWS_WITH(expr, matcher) \ - INTERNAL_CATCH_THROWS_STR_MATCHES("CATCH_REQUIRE_THROWS_WITH", \ - Catch::ResultDisposition::Normal, matcher, expr) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) \ - INTERNAL_CATCH_THROWS_MATCHES("CATCH_REQUIRE_THROWS_MATCHES", \ - exceptionType, Catch::ResultDisposition::Normal, matcher, expr) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_REQUIRE_NOTHROW(...) \ - INTERNAL_CATCH_NO_THROW("CATCH_REQUIRE_NOTHROW", \ - Catch::ResultDisposition::Normal, __VA_ARGS__) - -#define CATCH_CHECK(...) \ - INTERNAL_CATCH_TEST("CATCH_CHECK", \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define CATCH_CHECK_FALSE(...) \ - INTERNAL_CATCH_TEST("CATCH_CHECK_FALSE", \ - Catch::ResultDisposition::ContinueOnFailure | \ - Catch::ResultDisposition::FalseTest, \ - __VA_ARGS__) -#define CATCH_CHECKED_IF(...) \ - INTERNAL_CATCH_IF("CATCH_CHECKED_IF", \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define CATCH_CHECKED_ELSE(...) \ - INTERNAL_CATCH_ELSE("CATCH_CHECKED_ELSE", \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define CATCH_CHECK_NOFAIL(...) \ - INTERNAL_CATCH_TEST("CATCH_CHECK_NOFAIL", \ - Catch::ResultDisposition::ContinueOnFailure | \ - Catch::ResultDisposition::SuppressFail, \ - __VA_ARGS__) - -#define CATCH_CHECK_THROWS(...) \ - INTERNAL_CATCH_THROWS("CATCH_CHECK_THROWS", \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define CATCH_CHECK_THROWS_AS(expr, exceptionType) \ - INTERNAL_CATCH_THROWS_AS("CATCH_CHECK_THROWS_AS", exceptionType, \ - Catch::ResultDisposition::ContinueOnFailure, expr) -#define CATCH_CHECK_THROWS_WITH(expr, matcher) \ - INTERNAL_CATCH_THROWS_STR_MATCHES("CATCH_CHECK_THROWS_WITH", \ - Catch::ResultDisposition::ContinueOnFailure, matcher, expr) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THROWS_MATCHES(expr, exceptionType, matcher) \ - INTERNAL_CATCH_THROWS_MATCHES("CATCH_CHECK_THROWS_MATCHES", exceptionType, \ - Catch::ResultDisposition::ContinueOnFailure, matcher, expr) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_CHECK_NOTHROW(...) \ - INTERNAL_CATCH_NO_THROW("CATCH_CHECK_NOTHROW", \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) - -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THAT(arg, matcher) \ - INTERNAL_CHECK_THAT("CATCH_CHECK_THAT", matcher, \ - Catch::ResultDisposition::ContinueOnFailure, arg) - -#define CATCH_REQUIRE_THAT(arg, matcher) \ - INTERNAL_CHECK_THAT( \ - "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg) -#endif // CATCH_CONFIG_DISABLE_MATCHERS - -#define CATCH_INFO(msg) INTERNAL_CATCH_INFO("CATCH_INFO", msg) -#define CATCH_UNSCOPED_INFO(msg) \ - INTERNAL_CATCH_UNSCOPED_INFO("CATCH_UNSCOPED_INFO", msg) -#define CATCH_WARN(msg) \ - INTERNAL_CATCH_MSG("CATCH_WARN", Catch::ResultWas::Warning, \ - Catch::ResultDisposition::ContinueOnFailure, msg) -#define CATCH_CAPTURE(...) \ - INTERNAL_CATCH_CAPTURE( \ - INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__) - -#define CATCH_TEST_CASE(...) INTERNAL_CATCH_TESTCASE(__VA_ARGS__) -#define CATCH_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TEST_CASE_METHOD(className, __VA_ARGS__) -#define CATCH_METHOD_AS_TEST_CASE(method, ...) \ - INTERNAL_CATCH_METHOD_AS_TEST_CASE(method, __VA_ARGS__) -#define CATCH_REGISTER_TEST_CASE(Function, ...) \ - INTERNAL_CATCH_REGISTER_TESTCASE(Function, __VA_ARGS__) -#define CATCH_SECTION(...) INTERNAL_CATCH_SECTION(__VA_ARGS__) -#define CATCH_DYNAMIC_SECTION(...) INTERNAL_CATCH_DYNAMIC_SECTION(__VA_ARGS__) -#define CATCH_FAIL(...) \ - INTERNAL_CATCH_MSG("CATCH_FAIL", Catch::ResultWas::ExplicitFailure, \ - Catch::ResultDisposition::Normal, __VA_ARGS__) -#define CATCH_FAIL_CHECK(...) \ - INTERNAL_CATCH_MSG("CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define CATCH_SUCCEED(...) \ - INTERNAL_CATCH_MSG("CATCH_SUCCEED", Catch::ResultWas::Ok, \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) - -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() - -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define CATCH_TEMPLATE_TEST_CASE(...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__) -#define CATCH_TEMPLATE_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(__VA_ARGS__) -#define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) -#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, __VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE(...) \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(__VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(__VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, __VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, __VA_ARGS__) -#else -#define CATCH_TEMPLATE_TEST_CASE(...) \ - INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)) -#define CATCH_TEMPLATE_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(__VA_ARGS__)) -#define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)) -#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, __VA_ARGS__)) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(__VA_ARGS__)) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(__VA_ARGS__)) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( \ - className, __VA_ARGS__)) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( \ - className, __VA_ARGS__)) -#endif - -#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) -#define CATCH_STATIC_REQUIRE(...) \ - static_assert(__VA_ARGS__, #__VA_ARGS__); \ - CATCH_SUCCEED(#__VA_ARGS__) -#define CATCH_STATIC_REQUIRE_FALSE(...) \ - static_assert(!(__VA_ARGS__), "!(" #__VA_ARGS__ ")"); \ - CATCH_SUCCEED(#__VA_ARGS__) -#else -#define CATCH_STATIC_REQUIRE(...) CATCH_REQUIRE(__VA_ARGS__) -#define CATCH_STATIC_REQUIRE_FALSE(...) CATCH_REQUIRE_FALSE(__VA_ARGS__) -#endif - -// "BDD-style" convenience wrappers -#define CATCH_SCENARIO(...) CATCH_TEST_CASE("Scenario: " __VA_ARGS__) -#define CATCH_SCENARIO_METHOD(className, ...) \ - INTERNAL_CATCH_TEST_CASE_METHOD(className, "Scenario: " __VA_ARGS__) -#define CATCH_GIVEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Given: " << desc) -#define CATCH_AND_GIVEN(desc) \ - INTERNAL_CATCH_DYNAMIC_SECTION("And given: " << desc) -#define CATCH_WHEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" When: " << desc) -#define CATCH_AND_WHEN(desc) \ - INTERNAL_CATCH_DYNAMIC_SECTION(" And when: " << desc) -#define CATCH_THEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Then: " << desc) -#define CATCH_AND_THEN(desc) \ - INTERNAL_CATCH_DYNAMIC_SECTION(" And: " << desc) - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -#define CATCH_BENCHMARK(...) \ - INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), \ - INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__, , ), \ - INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__, , )) -#define CATCH_BENCHMARK_ADVANCED(name) \ - INTERNAL_CATCH_BENCHMARK_ADVANCED( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name) -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not -// required -#else - -#define REQUIRE(...) \ - INTERNAL_CATCH_TEST( \ - "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__) -#define REQUIRE_FALSE(...) \ - INTERNAL_CATCH_TEST("REQUIRE_FALSE", \ - Catch::ResultDisposition::Normal | \ - Catch::ResultDisposition::FalseTest, \ - __VA_ARGS__) - -#define REQUIRE_THROWS(...) \ - INTERNAL_CATCH_THROWS( \ - "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__) -#define REQUIRE_THROWS_AS(expr, exceptionType) \ - INTERNAL_CATCH_THROWS_AS("REQUIRE_THROWS_AS", exceptionType, \ - Catch::ResultDisposition::Normal, expr) -#define REQUIRE_THROWS_WITH(expr, matcher) \ - INTERNAL_CATCH_THROWS_STR_MATCHES("REQUIRE_THROWS_WITH", \ - Catch::ResultDisposition::Normal, matcher, expr) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) \ - INTERNAL_CATCH_THROWS_MATCHES("REQUIRE_THROWS_MATCHES", exceptionType, \ - Catch::ResultDisposition::Normal, matcher, expr) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define REQUIRE_NOTHROW(...) \ - INTERNAL_CATCH_NO_THROW( \ - "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__) - -#define CHECK(...) \ - INTERNAL_CATCH_TEST( \ - "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define CHECK_FALSE(...) \ - INTERNAL_CATCH_TEST("CHECK_FALSE", \ - Catch::ResultDisposition::ContinueOnFailure | \ - Catch::ResultDisposition::FalseTest, \ - __VA_ARGS__) -#define CHECKED_IF(...) \ - INTERNAL_CATCH_IF("CHECKED_IF", \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define CHECKED_ELSE(...) \ - INTERNAL_CATCH_ELSE("CHECKED_ELSE", \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define CHECK_NOFAIL(...) \ - INTERNAL_CATCH_TEST("CHECK_NOFAIL", \ - Catch::ResultDisposition::ContinueOnFailure | \ - Catch::ResultDisposition::SuppressFail, \ - __VA_ARGS__) - -#define CHECK_THROWS(...) \ - INTERNAL_CATCH_THROWS("CHECK_THROWS", \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define CHECK_THROWS_AS(expr, exceptionType) \ - INTERNAL_CATCH_THROWS_AS("CHECK_THROWS_AS", exceptionType, \ - Catch::ResultDisposition::ContinueOnFailure, expr) -#define CHECK_THROWS_WITH(expr, matcher) \ - INTERNAL_CATCH_THROWS_STR_MATCHES("CHECK_THROWS_WITH", \ - Catch::ResultDisposition::ContinueOnFailure, matcher, expr) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THROWS_MATCHES(expr, exceptionType, matcher) \ - INTERNAL_CATCH_THROWS_MATCHES("CHECK_THROWS_MATCHES", exceptionType, \ - Catch::ResultDisposition::ContinueOnFailure, matcher, expr) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CHECK_NOTHROW(...) \ - INTERNAL_CATCH_NO_THROW("CHECK_NOTHROW", \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) - -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THAT(arg, matcher) \ - INTERNAL_CHECK_THAT("CHECK_THAT", matcher, \ - Catch::ResultDisposition::ContinueOnFailure, arg) - -#define REQUIRE_THAT(arg, matcher) \ - INTERNAL_CHECK_THAT( \ - "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg) -#endif // CATCH_CONFIG_DISABLE_MATCHERS - -#define INFO(msg) INTERNAL_CATCH_INFO("INFO", msg) -#define UNSCOPED_INFO(msg) INTERNAL_CATCH_UNSCOPED_INFO("UNSCOPED_INFO", msg) -#define WARN(msg) \ - INTERNAL_CATCH_MSG("WARN", Catch::ResultWas::Warning, \ - Catch::ResultDisposition::ContinueOnFailure, msg) -#define CAPTURE(...) \ - INTERNAL_CATCH_CAPTURE( \ - INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__) - -#define TEST_CASE(...) INTERNAL_CATCH_TESTCASE(__VA_ARGS__) -#define TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TEST_CASE_METHOD(className, __VA_ARGS__) -#define METHOD_AS_TEST_CASE(method, ...) \ - INTERNAL_CATCH_METHOD_AS_TEST_CASE(method, __VA_ARGS__) -#define REGISTER_TEST_CASE(Function, ...) \ - INTERNAL_CATCH_REGISTER_TESTCASE(Function, __VA_ARGS__) -#define SECTION(...) INTERNAL_CATCH_SECTION(__VA_ARGS__) -#define DYNAMIC_SECTION(...) INTERNAL_CATCH_DYNAMIC_SECTION(__VA_ARGS__) -#define FAIL(...) \ - INTERNAL_CATCH_MSG("FAIL", Catch::ResultWas::ExplicitFailure, \ - Catch::ResultDisposition::Normal, __VA_ARGS__) -#define FAIL_CHECK(...) \ - INTERNAL_CATCH_MSG("FAIL_CHECK", Catch::ResultWas::ExplicitFailure, \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define SUCCEED(...) \ - INTERNAL_CATCH_MSG("SUCCEED", Catch::ResultWas::Ok, \ - Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__) -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() - -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define TEMPLATE_TEST_CASE(...) INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__) -#define TEMPLATE_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(__VA_ARGS__) -#define TEMPLATE_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) -#define TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, __VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE(...) \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(__VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(__VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, __VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, __VA_ARGS__) -#define TEMPLATE_LIST_TEST_CASE(...) \ - INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__) -#define TEMPLATE_LIST_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(className, __VA_ARGS__) -#else -#define TEMPLATE_TEST_CASE(...) \ - INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)) -#define TEMPLATE_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(__VA_ARGS__)) -#define TEMPLATE_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)) -#define TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, __VA_ARGS__)) -#define TEMPLATE_PRODUCT_TEST_CASE(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(__VA_ARGS__)) -#define TEMPLATE_PRODUCT_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(__VA_ARGS__)) -#define TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( \ - className, __VA_ARGS__)) -#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( \ - className, __VA_ARGS__)) -#define TEMPLATE_LIST_TEST_CASE(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)) -#define TEMPLATE_LIST_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(className, __VA_ARGS__)) -#endif - -#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) -#define STATIC_REQUIRE(...) \ - static_assert(__VA_ARGS__, #__VA_ARGS__); \ - SUCCEED(#__VA_ARGS__) -#define STATIC_REQUIRE_FALSE(...) \ - static_assert(!(__VA_ARGS__), "!(" #__VA_ARGS__ ")"); \ - SUCCEED("!(" #__VA_ARGS__ ")") -#else -#define STATIC_REQUIRE(...) REQUIRE(__VA_ARGS__) -#define STATIC_REQUIRE_FALSE(...) REQUIRE_FALSE(__VA_ARGS__) -#endif - -#endif - -#define CATCH_TRANSLATE_EXCEPTION(signature) \ - INTERNAL_CATCH_TRANSLATE_EXCEPTION(signature) - -// "BDD-style" convenience wrappers -#define SCENARIO(...) TEST_CASE("Scenario: " __VA_ARGS__) -#define SCENARIO_METHOD(className, ...) \ - INTERNAL_CATCH_TEST_CASE_METHOD(className, "Scenario: " __VA_ARGS__) - -#define GIVEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Given: " << desc) -#define AND_GIVEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION("And given: " << desc) -#define WHEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" When: " << desc) -#define AND_WHEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" And when: " << desc) -#define THEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Then: " << desc) -#define AND_THEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" And: " << desc) - -#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) -#define BENCHMARK(...) \ - INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), \ - INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__, , ), \ - INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__, , )) -#define BENCHMARK_ADVANCED(name) \ - INTERNAL_CATCH_BENCHMARK_ADVANCED( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name) -#endif // CATCH_CONFIG_ENABLE_BENCHMARKING - -using Catch::Detail::Approx; - -#else // CATCH_CONFIG_DISABLE - -////// -// If this config identifier is defined then all CATCH macros are prefixed with -// CATCH_ -#ifdef CATCH_CONFIG_PREFIX_ALL - -#define CATCH_REQUIRE(...) (void)(0) -#define CATCH_REQUIRE_FALSE(...) (void)(0) - -#define CATCH_REQUIRE_THROWS(...) (void)(0) -#define CATCH_REQUIRE_THROWS_AS(expr, exceptionType) (void)(0) -#define CATCH_REQUIRE_THROWS_WITH(expr, matcher) (void)(0) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_REQUIRE_NOTHROW(...) (void)(0) - -#define CATCH_CHECK(...) (void)(0) -#define CATCH_CHECK_FALSE(...) (void)(0) -#define CATCH_CHECKED_IF(...) if (__VA_ARGS__) -#define CATCH_CHECKED_ELSE(...) if (!(__VA_ARGS__)) -#define CATCH_CHECK_NOFAIL(...) (void)(0) - -#define CATCH_CHECK_THROWS(...) (void)(0) -#define CATCH_CHECK_THROWS_AS(expr, exceptionType) (void)(0) -#define CATCH_CHECK_THROWS_WITH(expr, matcher) (void)(0) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CATCH_CHECK_NOTHROW(...) (void)(0) - -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CATCH_CHECK_THAT(arg, matcher) (void)(0) - -#define CATCH_REQUIRE_THAT(arg, matcher) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS - -#define CATCH_INFO(msg) (void)(0) -#define CATCH_UNSCOPED_INFO(msg) (void)(0) -#define CATCH_WARN(msg) (void)(0) -#define CATCH_CAPTURE(msg) (void)(0) - -#define CATCH_TEST_CASE(...) \ - INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_T_E_S_T_)) -#define CATCH_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_T_E_S_T_)) -#define CATCH_METHOD_AS_TEST_CASE(method, ...) -#define CATCH_REGISTER_TEST_CASE(Function, ...) (void)(0) -#define CATCH_SECTION(...) -#define CATCH_DYNAMIC_SECTION(...) -#define CATCH_FAIL(...) (void)(0) -#define CATCH_FAIL_CHECK(...) (void)(0) -#define CATCH_SUCCEED(...) (void)(0) - -#define CATCH_ANON_TEST_CASE() \ - INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_T_E_S_T_)) - -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define CATCH_TEMPLATE_TEST_CASE(...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) -#define CATCH_TEMPLATE_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) -#define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( \ - className, __VA_ARGS__) -#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( \ - className, __VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE(...) \ - CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(...) \ - CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \ - CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \ - CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) -#else -#define CATCH_TEMPLATE_TEST_CASE(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)) -#define CATCH_TEMPLATE_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)) -#define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( \ - className, __VA_ARGS__)) -#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( \ - className, __VA_ARGS__)) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE(...) \ - CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(...) \ - CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \ - CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) -#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \ - CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) -#endif - -// "BDD-style" convenience wrappers -#define CATCH_SCENARIO(...) \ - INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_T_E_S_T_)) -#define CATCH_SCENARIO_METHOD(className, ...) \ - INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_T_E_S_T_), className) -#define CATCH_GIVEN(desc) -#define CATCH_AND_GIVEN(desc) -#define CATCH_WHEN(desc) -#define CATCH_AND_WHEN(desc) -#define CATCH_THEN(desc) -#define CATCH_AND_THEN(desc) - -#define CATCH_STATIC_REQUIRE(...) (void)(0) -#define CATCH_STATIC_REQUIRE_FALSE(...) (void)(0) - -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not -// required -#else - -#define REQUIRE(...) (void)(0) -#define REQUIRE_FALSE(...) (void)(0) - -#define REQUIRE_THROWS(...) (void)(0) -#define REQUIRE_THROWS_AS(expr, exceptionType) (void)(0) -#define REQUIRE_THROWS_WITH(expr, matcher) (void)(0) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define REQUIRE_NOTHROW(...) (void)(0) - -#define CHECK(...) (void)(0) -#define CHECK_FALSE(...) (void)(0) -#define CHECKED_IF(...) if (__VA_ARGS__) -#define CHECKED_ELSE(...) if (!(__VA_ARGS__)) -#define CHECK_NOFAIL(...) (void)(0) - -#define CHECK_THROWS(...) (void)(0) -#define CHECK_THROWS_AS(expr, exceptionType) (void)(0) -#define CHECK_THROWS_WITH(expr, matcher) (void)(0) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#define CHECK_NOTHROW(...) (void)(0) - -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define CHECK_THAT(arg, matcher) (void)(0) - -#define REQUIRE_THAT(arg, matcher) (void)(0) -#endif // CATCH_CONFIG_DISABLE_MATCHERS - -#define INFO(msg) (void)(0) -#define UNSCOPED_INFO(msg) (void)(0) -#define WARN(msg) (void)(0) -#define CAPTURE(msg) (void)(0) - -#define TEST_CASE(...) \ - INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_T_E_S_T_)) -#define TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_T_E_S_T_)) -#define METHOD_AS_TEST_CASE(method, ...) -#define REGISTER_TEST_CASE(Function, ...) (void)(0) -#define SECTION(...) -#define DYNAMIC_SECTION(...) -#define FAIL(...) (void)(0) -#define FAIL_CHECK(...) (void)(0) -#define SUCCEED(...) (void)(0) -#define ANON_TEST_CASE() \ - INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_T_E_S_T_)) - -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define TEMPLATE_TEST_CASE(...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) -#define TEMPLATE_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) -#define TEMPLATE_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( \ - className, __VA_ARGS__) -#define TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( \ - className, __VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE(...) TEMPLATE_TEST_CASE(__VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE_SIG(...) TEMPLATE_TEST_CASE(__VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \ - TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \ - TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) -#else -#define TEMPLATE_TEST_CASE(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)) -#define TEMPLATE_TEST_CASE_SIG(...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)) -#define TEMPLATE_TEST_CASE_METHOD(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( \ - className, __VA_ARGS__)) -#define TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( \ - className, __VA_ARGS__)) -#define TEMPLATE_PRODUCT_TEST_CASE(...) TEMPLATE_TEST_CASE(__VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE_SIG(...) TEMPLATE_TEST_CASE(__VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \ - TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) -#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \ - TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__) -#endif - -#define STATIC_REQUIRE(...) (void)(0) -#define STATIC_REQUIRE_FALSE(...) (void)(0) - -#endif - -#define CATCH_TRANSLATE_EXCEPTION(signature) \ - INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( \ - INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionTranslator), \ - signature) - -// "BDD-style" convenience wrappers -#define SCENARIO(...) \ - INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_T_E_S_T_)) -#define SCENARIO_METHOD(className, ...) \ - INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( \ - INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_T_E_S_T_), className) - -#define GIVEN(desc) -#define AND_GIVEN(desc) -#define WHEN(desc) -#define AND_WHEN(desc) -#define THEN(desc) -#define AND_THEN(desc) - -using Catch::Detail::Approx; - -#endif - -#endif // ! CATCH_CONFIG_IMPL_ONLY - -// start catch_reenable_warnings.h - -#ifdef __clang__ -#ifdef __ICC // icpc defines the __clang__ macro -#pragma warning(pop) -#else -#pragma clang diagnostic pop -#endif -#elif defined __GNUC__ -#pragma GCC diagnostic pop -#endif - -// end catch_reenable_warnings.h -// end catch.hpp -#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED diff --git a/tests/t00002/test_case.h b/tests/t00002/test_case.h index ed269e3a..7a237d5f 100644 --- a/tests/t00002/test_case.h +++ b/tests/t00002/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00002/test_case.cc + * tests/t00002/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,150 +16,84 @@ * limitations under the License. */ -TEST_CASE("t00002", "[test-case][class]") +TEST_CASE("t00002") { - auto [config, db] = load_config("t00002"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t00002_class"]; - - REQUIRE(diagram->name == "t00002_class"); + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00002", "t00002_class"); REQUIRE(diagram->include().namespaces.size() == 1); - REQUIRE(diagram->exclude().namespaces.size() == 0); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00002_class"); - REQUIRE(model->should_include({"clanguml", "t00002"}, "A")); REQUIRE(!model->should_include({"std"}, "vector")); - { - auto puml = generate_class_puml(diagram, *model); - AliasMatcher _A(puml); + CHECK_CLASS_DIAGRAM( + config, diagram, *model, + // Common test case for all diagram types + [](const auto &src) { + REQUIRE(HasTitle(src, "Basic class diagram example")); - REQUIRE_THAT(puml, StartsWith("@startuml")); - REQUIRE_THAT(puml, EndsWith("@enduml\n")); - REQUIRE_THAT(puml, HasTitle("Basic class diagram example")); - REQUIRE_THAT(puml, IsAbstractClass(_A("A"))); - REQUIRE_THAT(puml, IsClass(_A("B"))); - REQUIRE_THAT(puml, IsClass(_A("C"))); - REQUIRE_THAT(puml, IsClass(_A("D"))); - REQUIRE_THAT(puml, IsBaseClass(_A("A"), _A("B"))); - REQUIRE_THAT(puml, IsBaseClass(_A("A"), _A("C"))); - REQUIRE_THAT(puml, IsBaseClass(_A("B"), _A("D"))); - REQUIRE_THAT(puml, IsBaseClass(_A("C"), _A("D"))); - REQUIRE_THAT(puml, (IsMethod("foo_a"))); - REQUIRE_THAT(puml, (IsMethod("foo_c"))); + REQUIRE(!IsClass(src, "NOSUCHCLASS")); + REQUIRE(IsAbstractClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsBaseClass(src, "A", "B")); + REQUIRE(IsBaseClass(src, "A", "C")); + REQUIRE(IsBaseClass(src, "B", "D")); + REQUIRE(IsBaseClass(src, "C", "D")); - REQUIRE_THAT(puml, IsAssociation(_A("D"), _A("A"), "-as")); + REQUIRE(IsMethod(src, "A", "foo_a")); + REQUIRE(IsMethod(src, "C", "foo_c")); - REQUIRE_THAT(puml, HasNote(_A("A"), "left", "This is class A")); - REQUIRE_THAT(puml, HasNote(_A("B"), "top", "This is class B")); + REQUIRE(IsAssociation(src, "D", "A", "as")); - REQUIRE_THAT(puml, - HasLink(_A("A"), + REQUIRE(HasNote(src, "A", "left", "This is class A")); + REQUIRE(HasNote(src, "B", "top", "This is class B")); + + REQUIRE(HasLink(src, "A", fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" "t00002/t00002.cc#L7", clanguml::util::get_git_commit()), "This is class A")); - REQUIRE_THAT(puml, - HasLink(_A("B"), + REQUIRE(HasLink(src, "B", fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" "t00002/t00002.cc#L16", clanguml::util::get_git_commit()), "This is class B")); - REQUIRE_THAT(puml, - HasMemberLink("+foo_a() : void", + REQUIRE(HasMemberLink(src, "+foo_a() : void", fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" "t00002/t00002.cc#L18", clanguml::util::get_git_commit()), "foo_a")); - REQUIRE_THAT(puml, - HasMemberLink("-as : std::vector", + REQUIRE(HasMemberLink(src, "-as : std::vector", fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" "t00002/t00002.cc#L83", clanguml::util::get_git_commit()), "as")); + }, + // Specific test case only for PlantUML diagram + [](const plantuml_t &src) { + REQUIRE(StartsWith(src, "@startuml"s)); + REQUIRE(EndsWith(src, "@enduml\n"s)); + }, + // Specific test case only for JSON diagram + [](const json_t &src) { + const auto &A = get_element(src, "A"); - save_puml(config.output_directory(), diagram->name + ".puml", puml); - } - { - auto j = generate_class_json(diagram, *model); + REQUIRE(A.has_value()); - using namespace json; - - const auto &A = get_element(j, "A"); - - CHECK(A.has_value()); - - CHECK(A.value()["type"] == "class"); - CHECK(A.value()["name"] == "A"); - CHECK(A.value()["display_name"] == "A"); - CHECK(A.value()["namespace"] == "clanguml::t00002"); - CHECK(A.value()["source_location"]["file"] == "t00002.cc"); - CHECK(A.value()["source_location"]["line"] == 7); - - REQUIRE(HasTitle(j, "Basic class diagram example")); - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsBaseClass(j, "A", "B")); - REQUIRE(IsBaseClass(j, "A", "C")); - REQUIRE(IsBaseClass(j, "B", "D")); - REQUIRE(IsBaseClass(j, "C", "D")); - REQUIRE(IsMethod(j, "A", "foo_a")); - REQUIRE(IsMethod(j, "C", "foo_c")); - REQUIRE(IsField(j, "E", "as", "std::vector")); - REQUIRE(IsAssociation(j, "D", "A", "as")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto mmd = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(mmd); - using mermaid::HasNote; - using mermaid::HasTitle; - using mermaid::IsAbstractClass; - - REQUIRE_THAT(mmd, HasTitle("Basic class diagram example")); - REQUIRE_THAT(mmd, Contains("classDiagram")); - REQUIRE_THAT(mmd, IsAbstractClass(_A("A"))); - REQUIRE_THAT(mmd, IsClass(_A("B"))); - REQUIRE_THAT(mmd, IsClass(_A("C"))); - REQUIRE_THAT(mmd, IsClass(_A("D"))); - REQUIRE_THAT(mmd, IsBaseClass(_A("A"), _A("B"))); - REQUIRE_THAT(mmd, IsBaseClass(_A("A"), _A("C"))); - REQUIRE_THAT(mmd, IsBaseClass(_A("B"), _A("D"))); - REQUIRE_THAT(mmd, IsBaseClass(_A("C"), _A("D"))); - - REQUIRE_THAT(mmd, IsAssociation(_A("D"), _A("A"), "-as")); - - REQUIRE_THAT(mmd, (mermaid::IsMethod("foo_a"))); - REQUIRE_THAT(mmd, (mermaid::IsMethod("foo_c"))); - - REQUIRE_THAT(mmd, HasNote(_A("A"), "left", "This is class A")); - REQUIRE_THAT(mmd, HasNote(_A("B"), "top", "This is class B")); - - REQUIRE_THAT(mmd, - mermaid::HasLink(_A("A"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t00002/t00002.cc#L7", - clanguml::util::get_git_commit()), - "This is class A")); - - REQUIRE_THAT(mmd, - mermaid::HasLink(_A("B"), - fmt::format("https://github.com/bkryza/clang-uml/blob/{}/tests/" - "t00002/t00002.cc#L16", - clanguml::util::get_git_commit()), - "This is class B")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd); - } + REQUIRE(A.value()["type"] == "class"); + REQUIRE(A.value()["name"] == "A"); + REQUIRE(A.value()["display_name"] == "A"); + REQUIRE(A.value()["namespace"] == "clanguml::t00002"); + REQUIRE(A.value()["source_location"]["file"] == "t00002.cc"); + REQUIRE(A.value()["source_location"]["line"] == 7); + }); } \ No newline at end of file diff --git a/tests/t00003/test_case.h b/tests/t00003/test_case.h index 9fc98f5a..b9e2897a 100644 --- a/tests/t00003/test_case.h +++ b/tests/t00003/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00003/test_case.cc + * tests/t00003/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,127 +16,48 @@ * limitations under the License. */ -TEST_CASE("t00003", "[test-case][class]") +TEST_CASE("t00003") { - auto [config, db] = load_config("t00003"); + using namespace clanguml::test; + using namespace std::string_literals; - auto diagram = config.diagrams["t00003_class"]; - - REQUIRE(diagram->name == "t00003_class"); + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00003", "t00003_class"); REQUIRE(diagram->include().namespaces.size() == 1); - REQUIRE(diagram->exclude().namespaces.size() == 0); - auto model = generate_class_diagram(*db, diagram); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); - REQUIRE(model->name() == "t00003_class"); + REQUIRE(!IsDependency(src, "A", "A")); - { - auto puml = generate_class_puml(diagram, *model); - AliasMatcher _A(puml); + REQUIRE(IsMethod(src, "A", "A")); + REQUIRE(IsMethod(src, "A", "A", "void", "A &&")); + REQUIRE(IsMethod(src, "A", "A", "void", "const A &")); - REQUIRE_THAT(puml, StartsWith("@startuml")); - REQUIRE_THAT(puml, EndsWith("@enduml\n")); - REQUIRE_THAT(puml, IsClass(_A("A"))); + REQUIRE(IsMethod(src, "A", "~A")); - REQUIRE_THAT(puml, !IsDependency(_A("A"), _A("A"))); + REQUIRE(IsMethod(src, "A", "basic_method")); + REQUIRE(IsMethod(src, "A", "static_method", "int")); + REQUIRE(IsMethod(src, "A", "const_method")); + REQUIRE(IsMethod(src, "A", "default_int", "int", "int i = 12")); + REQUIRE(IsMethod(src, "A", "default_string", "std::string", + "int i, std::string s = \"abc\"")); - REQUIRE_THAT(puml, (IsMethod("A"))); - REQUIRE_THAT(puml, (IsMethod("A", "void", "A &&"))); - REQUIRE_THAT( - puml, (IsMethod("A", "void", "const A &"))); + REQUIRE(IsMethod( + src, "A", "size", "std::size_t")); - REQUIRE_THAT(puml, (IsMethod("~A"))); + REQUIRE(IsMethod(src, "A", "protected_method")); + REQUIRE(IsMethod(src, "A", "private_method")); + REQUIRE(IsField(src, "A", "public_member", "int")); + REQUIRE(IsField(src, "A", "protected_member", "int")); + REQUIRE(IsField(src, "A", "private_member", "int")); + REQUIRE(IsField( + src, "A", "auto_member", "const unsigned long")); - REQUIRE_THAT(puml, (IsMethod("basic_method"))); - REQUIRE_THAT(puml, (IsMethod("static_method", "int"))); - REQUIRE_THAT(puml, (IsMethod("const_method"))); - REQUIRE_THAT( - puml, (IsMethod("default_int", "int", "int i = 12"))); - REQUIRE_THAT(puml, - (IsMethod("default_string", "std::string", - "int i, std::string s = \"abc\""))); - - REQUIRE_THAT( - puml, (IsMethod("size", "std::size_t"))); - - REQUIRE_THAT(puml, (IsMethod("protected_method"))); - REQUIRE_THAT(puml, (IsMethod("private_method"))); - REQUIRE_THAT(puml, (IsField("public_member", "int"))); - REQUIRE_THAT(puml, (IsField("protected_member", "int"))); - REQUIRE_THAT(puml, (IsField("private_member", "int"))); - REQUIRE_THAT(puml, - (IsField("auto_member", "const unsigned long"))); - - REQUIRE_THAT(puml, (IsField("a_", "int"))); - REQUIRE_THAT(puml, (IsField("b_", "int"))); - REQUIRE_THAT(puml, (IsField("c_", "int"))); - - save_puml(config.output_directory(), diagram->name + ".puml", puml); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsMethod(j, "A", "A")); - REQUIRE(IsMethod(j, "A", "~A")); - REQUIRE(IsMethod(j, "A", "basic_method")); - REQUIRE(IsMethod(j, "A", "static_method")); - REQUIRE(IsMethod(j, "A", "const_method")); - REQUIRE(IsMethod(j, "A", "default_int")); - REQUIRE(IsMethod(j, "A", "default_string")); - - REQUIRE(!IsDependency(j, "A", "A")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto mmd = generate_class_mermaid(diagram, *model); - mermaid::AliasMatcher _A(mmd); - - REQUIRE_THAT(mmd, IsClass(_A("A"))); - - REQUIRE_THAT(mmd, !IsDependency(_A("A"), _A("A"))); - - REQUIRE_THAT(mmd, (mermaid::IsMethod("A"))); - REQUIRE_THAT( - mmd, (mermaid::IsMethod("A", "void", "A &&"))); - REQUIRE_THAT(mmd, - (mermaid::IsMethod("A", "void", "const A &"))); - - REQUIRE_THAT(mmd, (mermaid::IsMethod("~A"))); - - REQUIRE_THAT(mmd, (mermaid::IsMethod("basic_method"))); - REQUIRE_THAT( - mmd, (mermaid::IsMethod("static_method", "int"))); - REQUIRE_THAT(mmd, (mermaid::IsMethod("const_method"))); - REQUIRE_THAT(mmd, - (mermaid::IsMethod("default_int", "int", "int i = 12"))); - REQUIRE_THAT(mmd, - (mermaid::IsMethod("default_string", "std::string", - "int i, std::string s = \"abc\""))); - - REQUIRE_THAT(mmd, - (mermaid::IsMethod( - "size", "std::size_t"))); - - REQUIRE_THAT(mmd, (mermaid::IsMethod("protected_method"))); - REQUIRE_THAT(mmd, (mermaid::IsMethod("private_method"))); - - REQUIRE_THAT(mmd, (IsField("public_member", "int"))); - REQUIRE_THAT(mmd, (IsField("protected_member", "int"))); - REQUIRE_THAT(mmd, (IsField("private_member", "int"))); - REQUIRE_THAT(mmd, - (IsField("auto_member", "const unsigned long"))); - - REQUIRE_THAT(mmd, (IsField("a_", "int"))); - REQUIRE_THAT(mmd, (IsField("b_", "int"))); - REQUIRE_THAT(mmd, (IsField("c_", "int"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd); - } + REQUIRE(IsField(src, "A", "a_", "int")); + REQUIRE(IsField(src, "A", "b_", "int")); + REQUIRE(IsField(src, "A", "c_", "int")); + }); } \ No newline at end of file diff --git a/tests/t00004/test_case.h b/tests/t00004/test_case.h index 1cf42b89..f13bcf59 100644 --- a/tests/t00004/test_case.h +++ b/tests/t00004/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00004/test_case.cc + * tests/t00004/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,109 +16,42 @@ * limitations under the License. */ -TEST_CASE("t00004", "[test-case][class]") +TEST_CASE("t00004") { - auto [config, db] = load_config("t00004"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00004_class"]; - - REQUIRE(diagram->name == "t00004_class"); + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00004", "t00004_class"); REQUIRE(diagram->include().namespaces.size() == 1); REQUIRE(diagram->exclude().namespaces.size() == 0); - auto model = generate_class_diagram(*db, diagram); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "A::AA")); + REQUIRE(IsClass(src, "A::AA::AAA")); + REQUIRE(IsEnum(src, "B::AA")); + REQUIRE(IsEnum(src, "A::AA::Lights")); + REQUIRE(IsInnerClass(src, "A", "A::AA")); + REQUIRE(IsInnerClass(src, "A::AA", "A::AA::AAA")); + REQUIRE(IsInnerClass(src, "A::AA", "A::AA::Lights")); - REQUIRE(model->name() == "t00004_class"); + REQUIRE(IsMethod(src, "A", "foo")); + REQUIRE(IsMethod(src, "A", "foo2")); - { - auto puml = generate_class_puml(diagram, *model); - AliasMatcher _A(puml); + REQUIRE(IsClassTemplate(src, "C")); + REQUIRE(IsInnerClass(src, "C", "C::AA")); + REQUIRE(IsInnerClass(src, "C::AA", "C::AA::AAA")); + REQUIRE(IsInnerClass(src, "C", "C::CC")); + REQUIRE(IsInnerClass(src, "C::AA", "C::AA::CCC")); - REQUIRE_THAT(puml, StartsWith("@startuml")); - REQUIRE_THAT(puml, EndsWith("@enduml\n")); - REQUIRE_THAT(puml, IsClass(_A("A"))); - REQUIRE_THAT(puml, IsClass(_A("A::AA"))); - REQUIRE_THAT(puml, IsClass(_A("A::AA::AAA"))); - REQUIRE_THAT(puml, IsEnum(_A("B::AA"))); - REQUIRE_THAT(puml, IsEnum(_A("A::AA::Lights"))); - REQUIRE_THAT(puml, IsInnerClass(_A("A"), _A("A::AA"))); - REQUIRE_THAT(puml, IsInnerClass(_A("A::AA"), _A("A::AA::AAA"))); - REQUIRE_THAT(puml, IsInnerClass(_A("A::AA"), _A("A::AA::Lights"))); + REQUIRE(IsInnerClass(src, "C", "C::B")); + REQUIRE(IsAggregation(src, "C", "C::B", "b_int")); + REQUIRE(!IsInnerClass(src, "C", "C::B")); + REQUIRE(IsInstantiation(src, "C::B", "C::B")); - REQUIRE_THAT(puml, (IsMethod("foo"))); - REQUIRE_THAT(puml, (IsMethod("foo2"))); - - REQUIRE_THAT(puml, IsClassTemplate("C", "T")); - REQUIRE_THAT(puml, IsInnerClass(_A("C"), _A("C::AA"))); - REQUIRE_THAT(puml, IsInnerClass(_A("C::AA"), _A("C::AA::AAA"))); - REQUIRE_THAT(puml, IsInnerClass(_A("C"), _A("C::CC"))); - REQUIRE_THAT(puml, IsInnerClass(_A("C::AA"), _A("C::AA::CCC"))); - - REQUIRE_THAT(puml, IsInnerClass(_A("C"), _A("C::B"))); - REQUIRE_THAT( - puml, IsAggregation(_A("C"), _A("C::B"), "+b_int")); - REQUIRE_THAT(puml, !IsInnerClass(_A("C"), _A("C::B"))); - REQUIRE_THAT(puml, IsInstantiation(_A("C::B"), _A("C::B"))); - - REQUIRE_THAT(puml, IsClass(_A("detail::D"))); - REQUIRE_THAT(puml, IsClass(_A("detail::D::DD"))); - REQUIRE_THAT(puml, IsEnum(_A("detail::D::AA"))); - - save_puml(config.output_directory(), diagram->name + ".puml", puml); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "A::AA")); - REQUIRE(IsClass(j, "A::AA::AAA")); - REQUIRE(IsEnum(j, "B::AA")); - REQUIRE(IsEnum(j, "A::AA::Lights")); - REQUIRE(IsInnerClass(j, "A", "A::AA")); - REQUIRE(IsInnerClass(j, "A::AA", "A::AA::AAA")); - REQUIRE(IsInnerClass(j, "A::AA", "A::AA::Lights")); - - REQUIRE(IsClassTemplate(j, "C")); - - REQUIRE(IsClass(j, "detail::D")); - REQUIRE(IsClass(j, "detail::D::DD")); - REQUIRE(IsEnum(j, "detail::D::AA")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto mmd = generate_class_mermaid(diagram, *model); - mermaid::AliasMatcher _A(mmd); - - REQUIRE_THAT(mmd, IsClass(_A("A"))); - REQUIRE_THAT(mmd, IsClass(_A("A::AA"))); - REQUIRE_THAT(mmd, IsClass(_A("A::AA::AAA"))); - REQUIRE_THAT(mmd, mermaid::IsEnum(_A("B::AA"))); - REQUIRE_THAT(mmd, mermaid::IsEnum(_A("A::AA::Lights"))); - REQUIRE_THAT(mmd, mermaid::IsInnerClass(_A("A"), _A("A::AA"))); - REQUIRE_THAT(mmd, mermaid::IsInnerClass(_A("A::AA"), _A("A::AA::AAA"))); - REQUIRE_THAT( - mmd, mermaid::IsInnerClass(_A("A::AA"), _A("A::AA::Lights"))); - - REQUIRE_THAT(mmd, IsClass(_A("C"))); - REQUIRE_THAT(mmd, mermaid::IsInnerClass(_A("C"), _A("C::AA"))); - REQUIRE_THAT(mmd, mermaid::IsInnerClass(_A("C::AA"), _A("C::AA::AAA"))); - REQUIRE_THAT(mmd, mermaid::IsInnerClass(_A("C"), _A("C::CC"))); - REQUIRE_THAT(mmd, mermaid::IsInnerClass(_A("C::AA"), _A("C::AA::CCC"))); - - REQUIRE_THAT(mmd, mermaid::IsInnerClass(_A("C"), _A("C::B"))); - REQUIRE_THAT(mmd, IsAggregation(_A("C"), _A("C::B"), "+b_int")); - REQUIRE_THAT(mmd, !mermaid::IsInnerClass(_A("C"), _A("C::B"))); - REQUIRE_THAT(mmd, IsInstantiation(_A("C::B"), _A("C::B"))); - - REQUIRE_THAT(mmd, IsClass(_A("detail::D"))); - REQUIRE_THAT(mmd, IsClass(_A("detail::D::DD"))); - REQUIRE_THAT(mmd, mermaid::IsEnum(_A("detail::D::AA"))); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd); - } + REQUIRE(IsClass(src, {"detail", "D"})); + REQUIRE(IsClass(src, {"detail", "D::DD"})); + REQUIRE(IsEnum(src, {"detail", "D::AA"})); + }); } \ No newline at end of file diff --git a/tests/t00005/test_case.h b/tests/t00005/test_case.h index b759a51f..44e60a26 100644 --- a/tests/t00005/test_case.h +++ b/tests/t00005/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00005/test_case.cc + * tests/t00005/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,124 +16,42 @@ * limitations under the License. */ -TEST_CASE("t00005", "[test-case][class]") +TEST_CASE("t00005") { - auto [config, db] = load_config("t00005"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00005_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00005", "t00005_class"); - REQUIRE(diagram->name == "t00005_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClass(src, "E")); + REQUIRE(IsClass(src, "F")); + REQUIRE(IsClass(src, "G")); + REQUIRE(IsClass(src, "H")); + REQUIRE(IsClass(src, "I")); + REQUIRE(IsClass(src, "J")); + REQUIRE(IsClass(src, "K")); + REQUIRE(IsClass(src, "R")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE((IsField(src, "R", "some_int", "int"))); + REQUIRE((IsField(src, "R", "some_int_pointer", "int *"))); + REQUIRE( + (IsField(src, "R", "some_int_pointer_pointer", "int **"))); - REQUIRE(model->name() == "t00005_class"); - - { - auto puml = generate_class_puml(diagram, *model); - AliasMatcher _A(puml); - - REQUIRE_THAT(puml, StartsWith("@startuml")); - REQUIRE_THAT(puml, EndsWith("@enduml\n")); - REQUIRE_THAT(puml, IsClass(_A("A"))); - REQUIRE_THAT(puml, IsClass(_A("B"))); - REQUIRE_THAT(puml, IsClass(_A("C"))); - REQUIRE_THAT(puml, IsClass(_A("D"))); - REQUIRE_THAT(puml, IsClass(_A("E"))); - REQUIRE_THAT(puml, IsClass(_A("F"))); - REQUIRE_THAT(puml, IsClass(_A("G"))); - REQUIRE_THAT(puml, IsClass(_A("H"))); - REQUIRE_THAT(puml, IsClass(_A("I"))); - REQUIRE_THAT(puml, IsClass(_A("J"))); - REQUIRE_THAT(puml, IsClass(_A("K"))); - REQUIRE_THAT(puml, IsClass(_A("R"))); - - REQUIRE_THAT(puml, (IsField("some_int", "int"))); - REQUIRE_THAT(puml, (IsField("some_int_pointer", "int *"))); - REQUIRE_THAT( - puml, (IsField("some_int_pointer_pointer", "int **"))); - - REQUIRE_THAT(puml, IsAggregation(_A("R"), _A("A"), "+a")); - REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("B"), "+b")); - REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("C"), "+c")); - REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("D"), "+d")); - REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("E"), "+e")); - REQUIRE_THAT(puml, IsAggregation(_A("R"), _A("F"), "+f")); - REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("G"), "+g")); - REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("H"), "+h")); - REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("I"), "+i")); - REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("J"), "+j")); - REQUIRE_THAT(puml, IsAssociation(_A("R"), _A("K"), "+k")); - - save_puml(config.output_directory(), diagram->name + ".puml", puml); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsClass(j, "D")); - REQUIRE(IsClass(j, "E")); - REQUIRE(IsClass(j, "F")); - REQUIRE(IsClass(j, "G")); - REQUIRE(IsClass(j, "H")); - REQUIRE(IsClass(j, "I")); - REQUIRE(IsClass(j, "J")); - REQUIRE(IsClass(j, "K")); - REQUIRE(IsClass(j, "R")); - - REQUIRE(IsAggregation(j, "R", "A", "a")); - REQUIRE(IsAssociation(j, "R", "B", "b")); - REQUIRE(IsAssociation(j, "R", "C", "c")); - REQUIRE(IsAssociation(j, "R", "D", "d")); - REQUIRE(IsAssociation(j, "R", "E", "e")); - REQUIRE(IsAggregation(j, "R", "F", "f")); - REQUIRE(IsAssociation(j, "R", "G", "g")); - REQUIRE(IsAssociation(j, "R", "H", "h")); - REQUIRE(IsAssociation(j, "R", "I", "i")); - REQUIRE(IsAssociation(j, "R", "J", "j")); - REQUIRE(IsAssociation(j, "R", "K", "k")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto mmd = generate_class_mermaid(diagram, *model); - mermaid::AliasMatcher _A(mmd); - - REQUIRE_THAT(mmd, StartsWith("classDiagram")); - REQUIRE_THAT(mmd, IsClass(_A("A"))); - REQUIRE_THAT(mmd, IsClass(_A("B"))); - REQUIRE_THAT(mmd, IsClass(_A("C"))); - REQUIRE_THAT(mmd, IsClass(_A("D"))); - REQUIRE_THAT(mmd, IsClass(_A("E"))); - REQUIRE_THAT(mmd, IsClass(_A("F"))); - REQUIRE_THAT(mmd, IsClass(_A("G"))); - REQUIRE_THAT(mmd, IsClass(_A("H"))); - REQUIRE_THAT(mmd, IsClass(_A("I"))); - REQUIRE_THAT(mmd, IsClass(_A("J"))); - REQUIRE_THAT(mmd, IsClass(_A("K"))); - REQUIRE_THAT(mmd, IsClass(_A("R"))); - - REQUIRE_THAT(mmd, (IsField("some_int", "int"))); - REQUIRE_THAT(mmd, (IsField("some_int_pointer", "int *"))); - REQUIRE_THAT( - mmd, (IsField("some_int_pointer_pointer", "int **"))); - - REQUIRE_THAT(mmd, IsAggregation(_A("R"), _A("A"), "+a")); - REQUIRE_THAT(mmd, IsAssociation(_A("R"), _A("B"), "+b")); - REQUIRE_THAT(mmd, IsAssociation(_A("R"), _A("C"), "+c")); - REQUIRE_THAT(mmd, IsAssociation(_A("R"), _A("D"), "+d")); - REQUIRE_THAT(mmd, IsAssociation(_A("R"), _A("E"), "+e")); - REQUIRE_THAT(mmd, IsAggregation(_A("R"), _A("F"), "+f")); - REQUIRE_THAT(mmd, IsAssociation(_A("R"), _A("G"), "+g")); - REQUIRE_THAT(mmd, IsAssociation(_A("R"), _A("H"), "+h")); - REQUIRE_THAT(mmd, IsAssociation(_A("R"), _A("I"), "+i")); - REQUIRE_THAT(mmd, IsAssociation(_A("R"), _A("J"), "+j")); - REQUIRE_THAT(mmd, IsAssociation(_A("R"), _A("K"), "+k")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd); - } + REQUIRE(IsAggregation(src, "R", "A", "a")); + REQUIRE(IsAssociation(src, "R", "B", "b")); + REQUIRE(IsAssociation(src, "R", "C", "c")); + REQUIRE(IsAssociation(src, "R", "D", "d")); + REQUIRE(IsAssociation(src, "R", "E", "e")); + REQUIRE(IsAggregation(src, "R", "F", "f")); + REQUIRE(IsAssociation(src, "R", "G", "g")); + REQUIRE(IsAssociation(src, "R", "H", "h")); + REQUIRE(IsAssociation(src, "R", "I", "i")); + REQUIRE(IsAssociation(src, "R", "J", "j")); + REQUIRE(IsAssociation(src, "R", "K", "k")); + }); } \ No newline at end of file diff --git a/tests/t00006/test_case.h b/tests/t00006/test_case.h index 7757aa7f..e56e49ea 100644 --- a/tests/t00006/test_case.h +++ b/tests/t00006/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00006/test_case.cc + * tests/t00006/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,139 +16,49 @@ * limitations under the License. */ -TEST_CASE("t00006", "[test-case][class]") +TEST_CASE("t00006") { - auto [config, db] = load_config("t00006"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00006_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00006", "t00006_class"); - REQUIRE(diagram->name == "t00006_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "D")); + REQUIRE(IsClass(src, "E")); + REQUIRE(IsClass(src, "F")); + REQUIRE(IsClass(src, "G")); + REQUIRE(IsClass(src, "H")); + REQUIRE(IsClass(src, "I")); + REQUIRE(IsClass(src, "J")); + REQUIRE(IsClass(src, "K")); + REQUIRE(IsClass(src, "L")); + REQUIRE(IsClass(src, "M")); + REQUIRE(IsClass(src, "N")); + REQUIRE(IsClass(src, "NN")); + REQUIRE(IsClass(src, "NNN")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00006_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - REQUIRE_THAT(src, IsClass(_A("H"))); - REQUIRE_THAT(src, IsClass(_A("I"))); - REQUIRE_THAT(src, IsClass(_A("J"))); - REQUIRE_THAT(src, IsClass(_A("K"))); - REQUIRE_THAT(src, IsClass(_A("L"))); - REQUIRE_THAT(src, IsClass(_A("M"))); - REQUIRE_THAT(src, IsClass(_A("N"))); - REQUIRE_THAT(src, IsClass(_A("NN"))); - REQUIRE_THAT(src, IsClass(_A("NNN"))); - - REQUIRE_THAT(src, - IsInstantiation( - _A("custom_container"), _A("custom_container"))); - - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("A"), "+a")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("B"), "+b")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("C"), "+c")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("D"), "+d")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("custom_container"), "+e")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("F"), "+f")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("G"), "+g")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("H"), "+h")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("I"), "+i")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("J"), "+j")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("K"), "+k")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("L"), "+lm")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("M"), "+lm")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("N"), "+ns")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("NN"), "+ns")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("NNN"), "+ns")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsClass(j, "D")); - REQUIRE(IsClass(j, "E")); - REQUIRE(IsClass(j, "F")); - REQUIRE(IsClass(j, "G")); - REQUIRE(IsClass(j, "H")); - REQUIRE(IsClass(j, "I")); - REQUIRE(IsClass(j, "J")); - REQUIRE(IsClass(j, "K")); - REQUIRE(IsClass(j, "L")); - REQUIRE(IsClass(j, "M")); - REQUIRE(IsClass(j, "N")); - REQUIRE(IsClass(j, "NN")); - REQUIRE(IsClass(j, "NNN")); - - REQUIRE(IsAggregation(j, "R", "custom_container", "e")); REQUIRE( - IsInstantiation(j, "custom_container", "custom_container")); + IsInstantiation(src, "custom_container", "custom_container")); - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - using mermaid::AliasMatcher; - - AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("D"))); - REQUIRE_THAT(src, IsClass(_A("E"))); - REQUIRE_THAT(src, IsClass(_A("F"))); - REQUIRE_THAT(src, IsClass(_A("G"))); - REQUIRE_THAT(src, IsClass(_A("H"))); - REQUIRE_THAT(src, IsClass(_A("I"))); - REQUIRE_THAT(src, IsClass(_A("J"))); - REQUIRE_THAT(src, IsClass(_A("K"))); - REQUIRE_THAT(src, IsClass(_A("L"))); - REQUIRE_THAT(src, IsClass(_A("M"))); - REQUIRE_THAT(src, IsClass(_A("N"))); - REQUIRE_THAT(src, IsClass(_A("NN"))); - REQUIRE_THAT(src, IsClass(_A("NNN"))); - - REQUIRE_THAT(src, - IsInstantiation( - _A("custom_container"), _A("custom_container"))); - - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("A"), "+a")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("B"), "+b")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("C"), "+c")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("D"), "+d")); - REQUIRE_THAT( - src, IsAggregation(_A("R"), _A("custom_container"), "+e")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("F"), "+f")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("G"), "+g")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("H"), "+h")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("I"), "+i")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("J"), "+j")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("K"), "+k")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("L"), "+lm")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("M"), "+lm")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("N"), "+ns")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("NN"), "+ns")); - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("NNN"), "+ns")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAggregation(src, "R", "A", "a")); + REQUIRE(IsAssociation(src, "R", "B", "b")); + REQUIRE(IsAggregation(src, "R", "C", "c")); + REQUIRE(IsAssociation(src, "R", "D", "d")); + REQUIRE(IsAggregation(src, "R", "custom_container", "e")); + REQUIRE(IsAggregation(src, "R", "F", "f")); + REQUIRE(IsAssociation(src, "R", "G", "g")); + REQUIRE(IsAggregation(src, "R", "H", "h")); + REQUIRE(IsAssociation(src, "R", "I", "i")); + REQUIRE(IsAggregation(src, "R", "J", "j")); + REQUIRE(IsAssociation(src, "R", "K", "k")); + REQUIRE(IsAggregation(src, "R", "L", "lm")); + REQUIRE(IsAggregation(src, "R", "M", "lm")); + REQUIRE(IsAggregation(src, "R", "N", "ns")); + REQUIRE(IsAggregation(src, "R", "NN", "ns")); + REQUIRE(IsAggregation(src, "R", "NNN", "ns")); + }); } \ No newline at end of file diff --git a/tests/t00007/test_case.h b/tests/t00007/test_case.h index 98bf9855..a8bc596e 100644 --- a/tests/t00007/test_case.h +++ b/tests/t00007/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00007/test_case.cc + * tests/t00007/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,64 +16,21 @@ * limitations under the License. */ -TEST_CASE("t00007", "[test-case][class]") +TEST_CASE("t00007") { - auto [config, db] = load_config("t00007"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00007_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00007", "t00007_class"); - REQUIRE(diagram->name == "t00007_class"); + CHECK_CLASS_DIAGRAM(config, diagram, *model, [](const auto &src) { + REQUIRE(IsClass(src, "A")); + REQUIRE(IsClass(src, "B")); + REQUIRE(IsClass(src, "C")); + REQUIRE(IsClass(src, "R")); - auto model = generate_class_diagram(*db, diagram); - - REQUIRE(model->name() == "t00007_class"); - - { - auto src = generate_class_puml(diagram, *model); - AliasMatcher _A(src); - - REQUIRE_THAT(src, StartsWith("@startuml")); - REQUIRE_THAT(src, EndsWith("@enduml\n")); - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("A"), "+a")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("B"), "+b")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("C"), "+c")); - - save_puml(config.output_directory(), diagram->name + ".puml", src); - } - { - auto j = generate_class_json(diagram, *model); - - using namespace json; - - REQUIRE(IsClass(j, "A")); - REQUIRE(IsClass(j, "B")); - REQUIRE(IsClass(j, "C")); - REQUIRE(IsClass(j, "R")); - REQUIRE(IsAggregation(j, "R", "A", "a")); - REQUIRE(IsAssociation(j, "R", "B", "b")); - REQUIRE(IsAssociation(j, "R", "C", "c")); - - save_json(config.output_directory(), diagram->name + ".json", j); - } - { - auto src = generate_class_mermaid(diagram, *model); - - mermaid::AliasMatcher _A(src); - - REQUIRE_THAT(src, IsClass(_A("A"))); - REQUIRE_THAT(src, IsClass(_A("B"))); - REQUIRE_THAT(src, IsClass(_A("C"))); - REQUIRE_THAT(src, IsClass(_A("R"))); - - REQUIRE_THAT(src, IsAggregation(_A("R"), _A("A"), "+a")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("B"), "+b")); - REQUIRE_THAT(src, IsAssociation(_A("R"), _A("C"), "+c")); - - save_mermaid(config.output_directory(), diagram->name + ".mmd", src); - } + REQUIRE(IsAggregation(src, "R", "A", "a")); + REQUIRE(IsAssociation(src, "R", "B", "b")); + REQUIRE(IsAssociation(src, "R", "C", "c")); + }); } \ No newline at end of file diff --git a/tests/t00008/test_case.h b/tests/t00008/test_case.h index 480500be..fb90fdc3 100644 --- a/tests/t00008/test_case.h +++ b/tests/t00008/test_case.h @@ -1,5 +1,5 @@ /** - * tests/t00008/test_case.cc + * tests/t00008/test_case.h * * Copyright (c) 2021-2024 Bartek Kryza * @@ -16,85 +16,42 @@ * limitations under the License. */ -TEST_CASE("t00008", "[test-case][class]") +TEST_CASE("t00008") { - auto [config, db] = load_config("t00008"); + using namespace clanguml::test; - auto diagram = config.diagrams["t00008_class"]; + auto [config, db, diagram, model] = + CHECK_CLASS_MODEL("t00008", "t00008_class"); - REQUIRE(diagram->name == "t00008_class"); + CHECK_CLASS_DIAGRAM( + config, diagram, *model, + [](const auto &src) { + // TODO: add option to resolve using declared types + // REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "A")); + REQUIRE(IsClassTemplate(src, "B>")); - auto model = generate_class_diagram(*db, diagram); + REQUIRE(IsField( + src, "A", "value", "T")); + REQUIRE(IsField( + src, "A", "pointer", "T *")); + REQUIRE(IsField( + src, "A", "reference", "T &")); + REQUIRE(IsField(src, "A", + "values", "std::vector