From bc929686e37e1b5d41a44e071cd15abe214f8425 Mon Sep 17 00:00:00 2001 From: yujun Date: Tue, 9 Apr 2024 15:32:49 +0800 Subject: [PATCH] [feature](debug point) add macro DBUG_RUN_CALLBACK (#33407) --- be/src/util/debug_points.h | 72 ++++++++++++++++-------------- be/test/util/debug_points_test.cpp | 23 ++++------ 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/be/src/util/debug_points.h b/be/src/util/debug_points.h index 76f0ccfcd7..2288c19b3c 100644 --- a/be/src/util/debug_points.h +++ b/be/src/util/debug_points.h @@ -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>(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>(dp->handler); -// handler(a); -// }); -//} +// int got_a = 0; // -// test code: +// std::function set_handler = [](int* a) { *a = 1000; }; +// std::function 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 set_handler = [](int& a) { a = 1000; }; -// std::function 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 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 T param(const std::string& key, T default_value = T()) { @@ -126,6 +119,16 @@ struct DebugPoint { return it->second; } } + + template + void execute_callback(ARGS... args) { + if (!callback.has_value()) { + throw std::invalid_argument("No set callback"); + } + + auto func = std::any_cast>(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(new DebugPoint {.handler = handler})); + template + void add_with_callback(const std::string& name, std::function callback) { + add(name, std::shared_ptr(new DebugPoint {.callback = callback})); } static DebugPoints* instance(); diff --git a/be/test/util/debug_points_test.cpp b/be/test/util/debug_points_test.cpp index c9827b0438..3efde436d6 100644 --- a/be/test/util/debug_points_test.cpp +++ b/be/test/util/debug_points_test.cpp @@ -96,32 +96,25 @@ TEST(DebugPointsTest, AddTest) { DebugPoints::instance()->get_debug_param_or_default("dbug4", "")); } -void demo_handler() { +void demo_callback() { int a = 0; - DBUG_EXECUTE_IF("set_a", { - auto handler = std::any_cast>(dp->handler); - handler(a); - }); - - DBUG_EXECUTE_IF("get_a", { - auto handler = std::any_cast>(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 set_handler = [](int& a) { a = 1000; }; + std::function set_handler = [](int* a) { *a = 1000; }; std::function 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); }