[feature](debug point) add macro DBUG_RUN_CALLBACK (#33407)

This commit is contained in:
yujun
2024-04-09 15:32:49 +08:00
committed by yiguolei
parent e4eb76212a
commit bc929686e3
2 changed files with 46 additions and 49 deletions

View File

@ -43,7 +43,6 @@
// define some common debug actions
// usage example: DBUG_EXECUTE_IF("xxx", DBUG_BLOCK);
#define DBUG_BLOCK \
{ \
LOG(INFO) << "start debug block " << DP_NAME; \
@ -53,41 +52,35 @@
LOG(INFO) << "end debug block " << DP_NAME; \
}
// example of debug point with handler.
// DBUG_RUN_CALLBACK is usually use in be ut, to exchange local variable between the injected code and callback code.
// usage example: DBUG_EXECUTE_IF("xxx", DBUG_RUN_CALLBACK(yyy,...));
#define DBUG_RUN_CALLBACK(...) \
{ dp->execute_callback(__VA_ARGS__); }
// example of debug point with callback.
//
// base code:
// void demo_callback() {
// int a = 0;
//
// void demo_handler() {
// int a = 0;
// DBUG_EXECUTE_IF("set_a", DBUG_RUN_CALLBACK(&a));
// DBUG_EXECUTE_IF("get_a", DBUG_RUN_CALLBACK(a));
// }
//
// DBUG_EXECUTE_IF("set_a", {
// auto handler = std::any_cast<std::function<void(int&)>>(dp->handler);
// handler(a);
// });
// TEST(DebugPointsTest, Callback) {
// config::enable_debug_points = true;
// DebugPoints::instance()->clear();
//
// DBUG_EXECUTE_IF("get_a", {
// auto handler = std::any_cast<std::function<void(int)>>(dp->handler);
// handler(a);
// });
//}
// int got_a = 0;
//
// test code:
// std::function<void(int*)> set_handler = [](int* a) { *a = 1000; };
// std::function<void(int)> get_handler = [&got_a](int a) { got_a = a; };
// DebugPoints::instance()->add_with_callback("set_a", set_handler);
// DebugPoints::instance()->add_with_callback("get_a", get_handler);
//
//TEST(DebugPointsTest, Handler) {
// config::enable_debug_points = true;
// DebugPoints::instance()->clear();
// demo_callback();
//
// int got_a = 0;
//
// std::function<void(int&)> set_handler = [](int& a) { a = 1000; };
// std::function<void(int)> get_handler = [&got_a](int a) { got_a = a; };
// DebugPoints::instance()->add_with_handler("set_a", set_handler);
// DebugPoints::instance()->add_with_handler("get_a", get_handler);
//
// demo_handler();
//
// EXPECT_EQ(1000, got_a);
//}
// EXPECT_EQ(1000, got_a);
// }
namespace doris {
@ -98,10 +91,10 @@ struct DebugPoint {
std::map<std::string, std::string> params;
// Usually `handler` use in be ut, to exchange local variable between base code and injected code,
// Usually `callback` use in be ut, to exchange local variable between callback code and injected code,
// or change with different injected handlers.
// test/util/debug_points_test.cpp#Handler give a example.
std::any handler;
// test/util/debug_points_test.cpp#Callback give a example.
std::any callback;
template <typename T>
T param(const std::string& key, T default_value = T()) {
@ -126,6 +119,16 @@ struct DebugPoint {
return it->second;
}
}
template <typename... ARGS>
void execute_callback(ARGS... args) {
if (!callback.has_value()) {
throw std::invalid_argument("No set callback");
}
auto func = std::any_cast<std::function<void(ARGS...)>>(callback);
func(args...);
}
};
class DebugPoints {
@ -163,8 +166,9 @@ public:
add_with_params(name, {{"value", fmt::format("{}", value)}});
}
void add_with_handler(const std::string& name, std::any handler) {
add(name, std::shared_ptr<DebugPoint>(new DebugPoint {.handler = handler}));
template <typename... ARGS>
void add_with_callback(const std::string& name, std::function<void(ARGS...)> callback) {
add(name, std::shared_ptr<DebugPoint>(new DebugPoint {.callback = callback}));
}
static DebugPoints* instance();

View File

@ -96,32 +96,25 @@ TEST(DebugPointsTest, AddTest) {
DebugPoints::instance()->get_debug_param_or_default<std::string>("dbug4", ""));
}
void demo_handler() {
void demo_callback() {
int a = 0;
DBUG_EXECUTE_IF("set_a", {
auto handler = std::any_cast<std::function<void(int&)>>(dp->handler);
handler(a);
});
DBUG_EXECUTE_IF("get_a", {
auto handler = std::any_cast<std::function<void(int)>>(dp->handler);
handler(a);
});
DBUG_EXECUTE_IF("set_a", DBUG_RUN_CALLBACK(&a));
DBUG_EXECUTE_IF("get_a", DBUG_RUN_CALLBACK(a));
}
TEST(DebugPointsTest, Handler) {
TEST(DebugPointsTest, Callback) {
config::enable_debug_points = true;
DebugPoints::instance()->clear();
int got_a = 0;
std::function<void(int&)> set_handler = [](int& a) { a = 1000; };
std::function<void(int*)> set_handler = [](int* a) { *a = 1000; };
std::function<void(int)> get_handler = [&got_a](int a) { got_a = a; };
DebugPoints::instance()->add_with_handler("set_a", set_handler);
DebugPoints::instance()->add_with_handler("get_a", get_handler);
DebugPoints::instance()->add_with_callback("set_a", set_handler);
DebugPoints::instance()->add_with_callback("get_a", get_handler);
demo_handler();
demo_callback();
EXPECT_EQ(1000, got_a);
}