diff --git a/tracetools/CMakeLists.txt b/tracetools/CMakeLists.txt
index a6327a5..2263184 100644
--- a/tracetools/CMakeLists.txt
+++ b/tracetools/CMakeLists.txt
@@ -87,8 +87,15 @@ else()
endif()
if(BUILD_TESTING)
+ find_package(ament_cmake_gtest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+
+ ament_add_gtest(test_utils test/test_utils.cpp)
+ if(TARGET test_utils)
+ target_link_libraries(test_utils ${PROJECT_NAME} -rdynamic)
+ target_include_directories(test_utils PRIVATE test/)
+ endif()
endif()
ament_package()
diff --git a/tracetools/include/tracetools/tp_call.h b/tracetools/include/tracetools/tp_call.h
index a1aaa13..1facd35 100644
--- a/tracetools/include/tracetools/tp_call.h
+++ b/tracetools/include/tracetools/tp_call.h
@@ -189,11 +189,13 @@ TRACEPOINT_EVENT(
rclcpp_callback_register,
TP_ARGS(
const void *, callback_arg,
- const char *, symbol_arg
+ const char *, symbol_arg,
+ const void *, address_arg
),
TP_FIELDS(
ctf_integer_hex(const void *, callback, callback_arg)
ctf_string(symbol, symbol_arg)
+ ctf_integer_hex(const void *, address, address_arg)
)
)
diff --git a/tracetools/include/tracetools/tracetools.h b/tracetools/include/tracetools/tracetools.h
index 2bf082d..b6c38f6 100644
--- a/tracetools/include/tracetools/tracetools.h
+++ b/tracetools/include/tracetools/tracetools.h
@@ -129,7 +129,8 @@ void TRACEPOINT(
void TRACEPOINT(
rclcpp_callback_register,
const void * callback,
- const char * function_symbol);
+ const char * function_symbol,
+ const void * address);
/**
* tp: callback_start
diff --git a/tracetools/package.xml b/tracetools/package.xml
index a3cf0c5..45e574a 100644
--- a/tracetools/package.xml
+++ b/tracetools/package.xml
@@ -15,6 +15,7 @@
liblttng-ust-dev
+ ament_cmake_gtest
ament_lint_auto
ament_lint_common
diff --git a/tracetools/src/tracetools.c b/tracetools/src/tracetools.c
index fc2b996..36103d1 100644
--- a/tracetools/src/tracetools.c
+++ b/tracetools/src/tracetools.c
@@ -182,13 +182,15 @@ void TRACEPOINT(
void TRACEPOINT(
rclcpp_callback_register,
const void * callback,
- const char * function_symbol)
+ const char * function_symbol,
+ const void * address)
{
CONDITIONAL_TP(
ros2,
rclcpp_callback_register,
callback,
- function_symbol);
+ function_symbol,
+ address);
}
void TRACEPOINT(
diff --git a/tracetools/src/utils.cpp b/tracetools/src/utils.cpp
index acb49cb..2190df9 100644
--- a/tracetools/src/utils.cpp
+++ b/tracetools/src/utils.cpp
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include
+
#if defined(TRACETOOLS_LTTNG_ENABLED) && !defined(_WIN32)
#include
#include
@@ -24,11 +26,13 @@ const char * get_symbol(void * funptr)
#if defined(TRACETOOLS_LTTNG_ENABLED) && !defined(_WIN32)
#define SYMBOL_LAMBDA "[lambda]"
if (funptr == 0) {
+ std::cout << "lamba!" << std::endl;
return SYMBOL_LAMBDA;
}
Dl_info info;
if (dladdr(funptr, &info) == 0) {
+ std::cout << "unknown!" << std::endl;
return SYMBOL_UNKNOWN;
}
diff --git a/tracetools/test/test_utils.cpp b/tracetools/test/test_utils.cpp
new file mode 100644
index 0000000..d60a3a0
--- /dev/null
+++ b/tracetools/test/test_utils.cpp
@@ -0,0 +1,67 @@
+// Copyright 2019 Robert Bosch GmbH
+//
+// 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.
+
+#include
+
+#include
+#include
+
+#include "tracetools/utils.hpp"
+#include "test_utils.hpp"
+
+int function_int_int(int num)
+{
+ return num + 1;
+}
+
+void function_generic_shared(const std::shared_ptr p)
+{
+ (void)p;
+}
+
+void function_generic_unique(const std::unique_ptr p)
+{
+ (void)p;
+}
+
+/*
+ Testing address and symbol resolution for std::function objects.
+ */
+TEST(TestUtils, valid_address_symbol) {
+ std::function f = &function_int_int;
+ std::function lambda = [](int num) {return num + 1;};
+ std::function l = lambda;
+
+ ASSERT_EQ(f(69), l(69));
+
+ // Address for an std::function with an underlying lambda should be nullptr
+ ASSERT_EQ(get_address(l), nullptr) << "get_address() for lambda std::function not 0";
+ // But address for one with an actual underlying function should be non-zero
+ ASSERT_GT(get_address(f), (void *)0) << "get_address() for function not valid";
+
+ ASSERT_STREQ(get_symbol(get_address(f)), "function_int_int(int)") << "invalid function name";
+
+ // Generic
+ std::function)> fg_shared = &function_generic_shared;
+ SomeGenericClass gc_shared;
+ gc_shared.set(fg_shared);
+ ASSERT_GT(gc_shared.get_address_(), (void *)0) << "generic -- address invalid";
+ ASSERT_STREQ(gc_shared.get_symbol_(), "function_generic_shared(std::shared_ptr)") << "generic -- symbol invalid";
+
+ std::function)> fg_unique = &function_generic_unique;
+ SomeGenericClass gc_unique;
+ gc_unique.set(fg_unique);
+ ASSERT_GT(gc_unique.get_address_(), (void *)0) << "generic -- address invalid";
+ ASSERT_STREQ(gc_unique.get_symbol_(), "function_generic_unique(std::unique_ptr >)") << "generic -- symbol invalid";
+}
diff --git a/tracetools/test/test_utils.hpp b/tracetools/test/test_utils.hpp
new file mode 100644
index 0000000..33e9605
--- /dev/null
+++ b/tracetools/test/test_utils.hpp
@@ -0,0 +1,66 @@
+#include
+#include
+
+#include "tracetools/utils.hpp"
+#include "function_traits.hpp"
+
+
+template
+class SomeGenericClass
+{
+using SharedPtrCallback = std::function)>;
+using UniquePtrCallback = std::function)>;
+
+public:
+ SomeGenericClass()
+ : my_callback_shared_(nullptr), my_callback_unique_(nullptr)
+ {}
+
+ template<
+ typename TheType,
+ typename std::enable_if<
+ rclcpp::function_traits::same_arguments<
+ TheType,
+ SharedPtrCallback
+ >::value
+ >::type * = nullptr
+ >
+ void set(TheType callback)
+ {
+ my_callback_shared_ = callback;
+ }
+
+ template<
+ typename TheType,
+ typename std::enable_if<
+ rclcpp::function_traits::same_arguments<
+ TheType,
+ UniquePtrCallback
+ >::value
+ >::type * = nullptr
+ >
+ void set(TheType callback)
+ {
+ my_callback_unique_ = callback;
+ }
+
+ void * get_address_()
+ {
+ if (my_callback_shared_) {
+ return get_address(my_callback_shared_);
+ } else if (my_callback_unique_) {
+ return get_address(my_callback_unique_);
+ } else {
+ return (void *)0;
+ }
+ }
+
+ const char * get_symbol_()
+ {
+ return get_symbol(get_address_());
+ }
+
+private:
+ SharedPtrCallback my_callback_shared_;
+ UniquePtrCallback my_callback_unique_;
+};