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/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 }} }