Added support for call expressions tracking through lambdas in function arguments (#168)
This commit is contained in:
17
tests/t20044/.clang-uml
Normal file
17
tests/t20044/.clang-uml
Normal file
@@ -0,0 +1,17 @@
|
||||
add_compile_flags:
|
||||
- -fparse-all-comments
|
||||
diagrams:
|
||||
t20044_sequence:
|
||||
type: sequence
|
||||
glob:
|
||||
- t20044.cc
|
||||
generate_message_comments: true
|
||||
include:
|
||||
namespaces:
|
||||
- clanguml::t20044
|
||||
exclude:
|
||||
namespaces:
|
||||
- clanguml::t20044::detail2
|
||||
using_namespace: clanguml::t20044
|
||||
from:
|
||||
- function: "clanguml::t20044::tmain()"
|
||||
100
tests/t20044/t20044.cc
Normal file
100
tests/t20044/t20044.cc
Normal file
@@ -0,0 +1,100 @@
|
||||
// #include "include/expected.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
|
||||
namespace clanguml {
|
||||
namespace t20044 {
|
||||
|
||||
enum class error { OK, FAIL };
|
||||
|
||||
namespace detail {
|
||||
// Trivial std::expected mock-up just for testing calls through lambda
|
||||
// expressions passed as arguments to methods
|
||||
template <typename V, typename E> class expected {
|
||||
private:
|
||||
std::optional<V> value_;
|
||||
std::optional<E> error_;
|
||||
|
||||
public:
|
||||
explicit expected(V v)
|
||||
: value_{std::move(v)}
|
||||
{
|
||||
}
|
||||
explicit expected(E e)
|
||||
: error_{std::move(e)}
|
||||
{
|
||||
}
|
||||
|
||||
const auto &value() const { return *value_; }
|
||||
|
||||
const auto &error() const { return *error_; }
|
||||
|
||||
template <class F> auto and_then(F &&f) &&
|
||||
{
|
||||
if (value_)
|
||||
return f(*value_);
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
namespace detail2 {
|
||||
template <typename F> void run(F &&f) { f(); }
|
||||
} // namespace detail2
|
||||
|
||||
using result_t = detail::expected<int, error>;
|
||||
|
||||
struct A {
|
||||
auto a() const { }
|
||||
|
||||
auto a1() const { return result_t{10}; }
|
||||
|
||||
auto a2(int arg) const { return result_t{arg + 1}; }
|
||||
|
||||
auto a4(int arg) const { return result_t{arg + 1}; }
|
||||
|
||||
void a5() { }
|
||||
};
|
||||
|
||||
auto a3(int arg) { return result_t{arg + 1}; }
|
||||
|
||||
struct R {
|
||||
template <typename F> R(F &&f) { f(); }
|
||||
};
|
||||
|
||||
int tmain()
|
||||
{
|
||||
A a;
|
||||
|
||||
// Call to template constructor with callable parameter and lambda
|
||||
// expression as argument
|
||||
R r([&a]() { a.a(); });
|
||||
|
||||
std::function<result_t(const A &, int)> a4_wrapper = &A::a4;
|
||||
|
||||
std::function<result_t(int)> a4_wrapper_to_a =
|
||||
std::bind(a4_wrapper, a, std::placeholders::_1);
|
||||
|
||||
// The message to detail2::run() is skipped due to exclude filter, however
|
||||
// the call to lambda and A::a5() is rendered
|
||||
// TODO: Add some marker to highlight that this is not a direct call
|
||||
detail2::run([&]() { a.a5(); });
|
||||
|
||||
return a
|
||||
.a1()
|
||||
// Call to a template method accepting a callable with lambda expression
|
||||
// as argument, fully tracked showing method's activity and
|
||||
.and_then([&](auto &&arg) { return a.a2(arg); })
|
||||
// TODO: Call to a method accepting a callable with function pointer
|
||||
// as argument
|
||||
.and_then(a3)
|
||||
// TODO: Call to a method accepting a callable with std::function as
|
||||
// argument
|
||||
.and_then(a4_wrapper_to_a)
|
||||
.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
91
tests/t20044/test_case.h
Normal file
91
tests/t20044/test_case.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* tests/t20044/test_case.h
|
||||
*
|
||||
* Copyright (c) 2021-2024 Bartek Kryza <bkryza@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
TEST_CASE("t20044", "[test-case][sequence]")
|
||||
{
|
||||
auto [config, db] = load_config("t20044");
|
||||
|
||||
auto diagram = config.diagrams["t20044_sequence"];
|
||||
|
||||
REQUIRE(diagram->name == "t20044_sequence");
|
||||
|
||||
auto model = generate_sequence_diagram(*db, diagram);
|
||||
|
||||
REQUIRE(model->name() == "t20044_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"), "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<int,error>"),
|
||||
"and_then((lambda at t20044.cc:90:19) &&)"));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(_A("detail::expected<int,error>"),
|
||||
_A("tmain()::(lambda t20044.cc:90:19)"), "operator()()"));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(
|
||||
_A("tmain()::(lambda t20044.cc:90:19)"), _A("A"), "a2(int)"));
|
||||
|
||||
REQUIRE_THAT(src,
|
||||
HasCall(
|
||||
_A("A"), _A("detail::expected<int,error>"), "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);
|
||||
}
|
||||
}
|
||||
@@ -470,6 +470,7 @@ using namespace clanguml::test::matchers;
|
||||
#include "t20041/test_case.h"
|
||||
#include "t20042/test_case.h"
|
||||
#include "t20043/test_case.h"
|
||||
#include "t20044/test_case.h"
|
||||
|
||||
///
|
||||
/// Package diagram tests
|
||||
|
||||
Reference in New Issue
Block a user