ros2_foxglove_bridge/tests/smoke_test.cpp
Go to the documentation of this file.
1 #define ASIO_STANDALONE
2 
3 #include <chrono>
4 #include <future>
5 #include <thread>
6 
7 #include <gtest/gtest.h>
8 #include <rclcpp_components/component_manager.hpp>
9 #include <std_msgs/msg/string.hpp>
10 #include <std_srvs/srv/set_bool.hpp>
11 #include <websocketpp/config/asio_client.hpp>
12 
15 
16 constexpr char URI[] = "ws://localhost:8765";
17 
18 // Binary representation of std_msgs/msg/String for "hello world"
19 constexpr uint8_t HELLO_WORLD_BINARY[] = {0, 1, 0, 0, 12, 0, 0, 0, 104, 101,
20  108, 108, 111, 32, 119, 111, 114, 108, 100, 0};
21 
22 constexpr auto ONE_SECOND = std::chrono::seconds(1);
23 constexpr auto DEFAULT_TIMEOUT = std::chrono::seconds(10);
24 
25 class ParameterTest : public ::testing::Test {
26 public:
27  using PARAM_1_TYPE = std::string;
28  inline static const std::string NODE_1_NAME = "node_1";
29  inline static const std::string PARAM_1_NAME = "string_param";
30  inline static const PARAM_1_TYPE PARAM_1_DEFAULT_VALUE = "hello";
31  inline static const std::string DELETABLE_PARAM_NAME = "deletable_param";
32 
33  using PARAM_2_TYPE = std::vector<int64_t>;
34  inline static const std::string NODE_2_NAME = "node_2";
35  inline static const std::string PARAM_2_NAME = "int_array_param";
36  inline static const PARAM_2_TYPE PARAM_2_DEFAULT_VALUE = {1, 2, 3};
37 
38 protected:
39  void SetUp() override {
40  auto nodeOptions = rclcpp::NodeOptions();
41  nodeOptions.allow_undeclared_parameters(true);
42  _paramNode1 = rclcpp::Node::make_shared(NODE_1_NAME, nodeOptions);
43  auto p1Param = rcl_interfaces::msg::ParameterDescriptor{};
44  p1Param.name = PARAM_1_NAME;
45  p1Param.type = rcl_interfaces::msg::ParameterType::PARAMETER_STRING;
46  p1Param.read_only = false;
47  _paramNode1->declare_parameter(p1Param.name, PARAM_1_DEFAULT_VALUE, p1Param);
48  _paramNode1->set_parameter(rclcpp::Parameter(DELETABLE_PARAM_NAME, true));
49 
50  _paramNode2 = rclcpp::Node::make_shared(NODE_2_NAME);
51  auto p2Param = rcl_interfaces::msg::ParameterDescriptor{};
52  p2Param.name = PARAM_2_NAME;
53  p2Param.type = rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY;
54  p2Param.read_only = false;
55  _paramNode2->declare_parameter(p2Param.name, PARAM_2_DEFAULT_VALUE, p2Param);
56 
57  _executor.add_node(_paramNode1);
58  _executor.add_node(_paramNode2);
59  _executorThread = std::thread([this]() {
60  _executor.spin();
61  });
62 
63  _wsClient = std::make_shared<foxglove::Client<websocketpp::config::asio_client>>();
64  ASSERT_EQ(std::future_status::ready, _wsClient->connect(URI).wait_for(DEFAULT_TIMEOUT));
65  }
66 
67  void TearDown() override {
68  _executor.cancel();
69  _executorThread.join();
70  }
71 
72  rclcpp::executors::SingleThreadedExecutor _executor;
73  rclcpp::Node::SharedPtr _paramNode1;
74  rclcpp::Node::SharedPtr _paramNode2;
75  std::thread _executorThread;
76  std::shared_ptr<foxglove::Client<websocketpp::config::asio_client>> _wsClient;
77 };
78 
79 class ServiceTest : public ::testing::Test {
80 public:
81  inline static const std::string SERVICE_NAME = "/foo_service";
82 
83 protected:
84  void SetUp() override {
85  _node = rclcpp::Node::make_shared("node");
86  _service = _node->create_service<std_srvs::srv::SetBool>(
87  SERVICE_NAME, [&](std::shared_ptr<std_srvs::srv::SetBool::Request> req,
88  std::shared_ptr<std_srvs::srv::SetBool::Response> res) {
89  res->message = "hello";
90  res->success = req->data;
91  });
92 
93  _executor.add_node(_node);
94  _executorThread = std::thread([this]() {
95  _executor.spin();
96  });
97  }
98 
99  void TearDown() override {
100  _executor.cancel();
101  _executorThread.join();
102  }
103 
104  rclcpp::executors::SingleThreadedExecutor _executor;
105  rclcpp::Node::SharedPtr _node;
106  rclcpp::ServiceBase::SharedPtr _service;
107  std::thread _executorThread;
108  std::shared_ptr<foxglove::Client<websocketpp::config::asio_client>> _wsClient;
109 };
110 
111 class ExistingPublisherTest : public ::testing::Test {
112 public:
113  inline static const std::string TOPIC_NAME = "/some_topic";
114 
115 protected:
116  void SetUp() override {
117  _node = rclcpp::Node::make_shared("node");
118  _publisher =
119  _node->create_publisher<std_msgs::msg::String>(TOPIC_NAME, rclcpp::SystemDefaultsQoS());
120  _executor.add_node(_node);
121  _executorThread = std::thread([this]() {
122  _executor.spin();
123  });
124  }
125 
126  void TearDown() override {
127  _executor.cancel();
128  _executorThread.join();
129  }
130 
131  rclcpp::executors::SingleThreadedExecutor _executor;
132  rclcpp::Node::SharedPtr _node;
133  rclcpp::PublisherBase::SharedPtr _publisher;
134  std::thread _executorThread;
135 };
136 
137 template <class T>
138 std::shared_ptr<rclcpp::SerializedMessage> serializeMsg(const T* msg) {
139  using rosidl_typesupport_cpp::get_message_type_support_handle;
140  auto typeSupportHdl = get_message_type_support_handle<T>();
141  auto result = std::make_shared<rclcpp::SerializedMessage>();
142  rmw_ret_t ret = rmw_serialize(msg, typeSupportHdl, &result->get_rcl_serialized_message());
143  EXPECT_EQ(ret, RMW_RET_OK);
144  return result;
145 }
146 
147 template <class T>
148 std::shared_ptr<T> deserializeMsg(const rcl_serialized_message_t* msg) {
149  using rosidl_typesupport_cpp::get_message_type_support_handle;
150  auto typeSupportHdl = get_message_type_support_handle<T>();
151  auto result = std::make_shared<T>();
152  rmw_ret_t ret = rmw_deserialize(msg, typeSupportHdl, result.get());
153  EXPECT_EQ(ret, RMW_RET_OK);
154  return result;
155 }
156 
157 TEST(SmokeTest, testConnection) {
159  EXPECT_EQ(std::future_status::ready, wsClient.connect(URI).wait_for(DEFAULT_TIMEOUT));
160 }
161 
162 TEST(SmokeTest, testSubscription) {
163  // Publish a string message on a latched ros topic
164  const std::string topic_name = "/pub_topic";
165  std_msgs::msg::String rosMsg;
166  rosMsg.data = "hello world";
167 
168  auto node = rclcpp::Node::make_shared("tester");
169  rclcpp::QoS qos = rclcpp::QoS{rclcpp::KeepLast(1lu)};
170  qos.transient_local();
171  auto pub = node->create_publisher<std_msgs::msg::String>(topic_name, qos);
172  pub->publish(rosMsg);
173 
174  // Connect a few clients and make sure that they receive the correct message
175  const auto clientCount = 3;
176  for (auto i = 0; i < clientCount; ++i) {
177  std::vector<uint8_t> msgData;
178  ASSERT_NO_THROW(msgData = foxglove::connectClientAndReceiveMsg(URI, topic_name));
179  ASSERT_EQ(sizeof(HELLO_WORLD_BINARY), msgData.size());
180  EXPECT_EQ(0, std::memcmp(HELLO_WORLD_BINARY, msgData.data(), msgData.size()));
181  }
182 }
183 
184 TEST(SmokeTest, testSubscriptionParallel) {
185  // Publish a string message on a latched ros topic
186  const std::string topic_name = "/pub_topic";
187  std_msgs::msg::String rosMsg;
188  rosMsg.data = "hello world";
189 
190  auto node = rclcpp::Node::make_shared("tester");
191  rclcpp::QoS qos = rclcpp::QoS{rclcpp::KeepLast(1lu)};
192  qos.transient_local();
193  auto pub = node->create_publisher<std_msgs::msg::String>(topic_name, qos);
194  pub->publish(rosMsg);
195 
196  // Connect a few clients (in parallel) and make sure that they receive the correct message
197  std::vector<std::future<std::vector<uint8_t>>> futures;
198  const auto clientCount = 3;
199  for (auto i = 0; i < clientCount; ++i) {
200  futures.push_back(
201  std::async(std::launch::async, foxglove::connectClientAndReceiveMsg, URI, topic_name));
202  }
203 
204  for (auto& future : futures) {
205  ASSERT_EQ(std::future_status::ready, future.wait_for(DEFAULT_TIMEOUT));
206  auto msgData = future.get();
207  ASSERT_EQ(sizeof(HELLO_WORLD_BINARY), msgData.size());
208  EXPECT_EQ(0, std::memcmp(HELLO_WORLD_BINARY, msgData.data(), msgData.size()));
209  }
210 }
211 
212 TEST(SmokeTest, testPublishing) {
213  foxglove::ClientAdvertisement advertisement;
214  advertisement.channelId = 1;
215  advertisement.topic = "/foo";
216  advertisement.encoding = "cdr";
217  advertisement.schemaName = "std_msgs/String";
218 
219  // Set up a ROS node with a subscriber
220  std::promise<std::string> msgPromise;
221  auto msgFuture = msgPromise.get_future();
222  auto node = rclcpp::Node::make_shared("tester");
223  auto sub = node->create_subscription<std_msgs::msg::String>(
224  advertisement.topic, 10, [&msgPromise](const std_msgs::msg::String::SharedPtr msg) {
225  msgPromise.set_value(msg->data);
226  });
227  rclcpp::executors::SingleThreadedExecutor executor;
228  executor.add_node(node);
229 
230  // Set up the client, advertise and publish the binary message
232  ASSERT_EQ(std::future_status::ready, wsClient.connect(URI).wait_for(DEFAULT_TIMEOUT));
233  wsClient.advertise({advertisement});
234  std::this_thread::sleep_for(ONE_SECOND);
235  wsClient.publish(advertisement.channelId, HELLO_WORLD_BINARY, sizeof(HELLO_WORLD_BINARY));
236  wsClient.unadvertise({advertisement.channelId});
237 
238  // Ensure that we have received the correct message via our ROS subscriber
239  const auto ret = executor.spin_until_future_complete(msgFuture, ONE_SECOND);
240  ASSERT_EQ(rclcpp::FutureReturnCode::SUCCESS, ret);
241  EXPECT_EQ("hello world", msgFuture.get());
242 }
243 
244 TEST_F(ExistingPublisherTest, testPublishingWithExistingPublisher) {
245  foxglove::ClientAdvertisement advertisement;
246  advertisement.channelId = 1;
247  advertisement.topic = TOPIC_NAME;
248  advertisement.encoding = "cdr";
249  advertisement.schemaName = "std_msgs/String";
250 
251  // Set up a ROS node with a subscriber
252  std::promise<std::string> msgPromise;
253  auto msgFuture = msgPromise.get_future();
254  auto node = rclcpp::Node::make_shared("tester");
255  auto sub = node->create_subscription<std_msgs::msg::String>(
256  advertisement.topic, 10, [&msgPromise](const std_msgs::msg::String::SharedPtr msg) {
257  msgPromise.set_value(msg->data);
258  });
259  rclcpp::executors::SingleThreadedExecutor executor;
260  executor.add_node(node);
261 
262  // Set up the client, advertise and publish the binary message
264  ASSERT_EQ(std::future_status::ready, wsClient.connect(URI).wait_for(DEFAULT_TIMEOUT));
265  wsClient.advertise({advertisement});
266  std::this_thread::sleep_for(ONE_SECOND);
267  wsClient.publish(advertisement.channelId, HELLO_WORLD_BINARY, sizeof(HELLO_WORLD_BINARY));
268  wsClient.unadvertise({advertisement.channelId});
269 
270  // Ensure that we have received the correct message via our ROS subscriber
271  const auto ret = executor.spin_until_future_complete(msgFuture, ONE_SECOND);
272  ASSERT_EQ(rclcpp::FutureReturnCode::SUCCESS, ret);
273  EXPECT_EQ("hello world", msgFuture.get());
274 }
275 
276 TEST_F(ParameterTest, testGetAllParams) {
277  const std::string requestId = "req-testGetAllParams";
278  auto future = foxglove::waitForParameters(_wsClient, requestId);
279  _wsClient->getParameters({}, requestId);
280  ASSERT_EQ(std::future_status::ready, future.wait_for(DEFAULT_TIMEOUT));
281  std::vector<foxglove::Parameter> params = future.get();
282 
283  EXPECT_GE(params.size(), 2UL);
284 }
285 
286 TEST_F(ParameterTest, testGetNonExistingParameters) {
287  const std::string requestId = "req-testGetNonExistingParameters";
288  auto future = foxglove::waitForParameters(_wsClient, requestId);
289  _wsClient->getParameters(
290  {"/foo_1.non_existing_parameter", "/foo_2.non_existing.nested_parameter"}, requestId);
291  ASSERT_EQ(std::future_status::ready, future.wait_for(DEFAULT_TIMEOUT));
292  std::vector<foxglove::Parameter> params = future.get();
293 
294  EXPECT_TRUE(params.empty());
295 }
296 
297 TEST_F(ParameterTest, testGetParameters) {
298  const auto p1 = NODE_1_NAME + "." + PARAM_1_NAME;
299  const auto p2 = NODE_2_NAME + "." + PARAM_2_NAME;
300 
301  const std::string requestId = "req-testGetParameters";
302  auto future = foxglove::waitForParameters(_wsClient, requestId);
303  _wsClient->getParameters({p1, p2}, requestId);
304  ASSERT_EQ(std::future_status::ready, future.wait_for(DEFAULT_TIMEOUT));
305  std::vector<foxglove::Parameter> params = future.get();
306 
307  EXPECT_EQ(2UL, params.size());
308  auto p1Iter = std::find_if(params.begin(), params.end(), [&p1](const auto& param) {
309  return param.getName() == p1;
310  });
311  auto p2Iter = std::find_if(params.begin(), params.end(), [&p2](const auto& param) {
312  return param.getName() == p2;
313  });
314  ASSERT_NE(p1Iter, params.end());
315  EXPECT_EQ(PARAM_1_DEFAULT_VALUE, p1Iter->getValue().getValue<PARAM_1_TYPE>());
316  ASSERT_NE(p2Iter, params.end());
317 
318  std::vector<int64_t> int_array_val;
319  const auto array_params = p2Iter->getValue().getValue<std::vector<foxglove::ParameterValue>>();
320  for (const auto& paramValue : array_params) {
321  int_array_val.push_back(paramValue.getValue<int64_t>());
322  }
323  EXPECT_EQ(int_array_val, PARAM_2_DEFAULT_VALUE);
324 }
325 
326 TEST_F(ParameterTest, testSetParameters) {
327  const auto p1 = NODE_1_NAME + "." + PARAM_1_NAME;
328  const auto p2 = NODE_2_NAME + "." + PARAM_2_NAME;
329  const PARAM_1_TYPE newP1value = "world";
330  const std::vector<foxglove::ParameterValue> newP2value = {4, 5, 6};
331 
332  const std::vector<foxglove::Parameter> parameters = {
333  foxglove::Parameter(p1, newP1value),
334  foxglove::Parameter(p2, newP2value),
335  };
336 
337  _wsClient->setParameters(parameters);
338  const std::string requestId = "req-testSetParameters";
339  auto future = foxglove::waitForParameters(_wsClient, requestId);
340  _wsClient->getParameters({p1, p2}, requestId);
341  ASSERT_EQ(std::future_status::ready, future.wait_for(DEFAULT_TIMEOUT));
342  std::vector<foxglove::Parameter> params = future.get();
343 
344  EXPECT_EQ(2UL, params.size());
345  auto p1Iter = std::find_if(params.begin(), params.end(), [&p1](const auto& param) {
346  return param.getName() == p1;
347  });
348  auto p2Iter = std::find_if(params.begin(), params.end(), [&p2](const auto& param) {
349  return param.getName() == p2;
350  });
351  ASSERT_NE(p1Iter, params.end());
352  EXPECT_EQ(newP1value, p1Iter->getValue().getValue<PARAM_1_TYPE>());
353  ASSERT_NE(p2Iter, params.end());
354 
355  std::vector<int64_t> int_array_val;
356  const auto array_params = p2Iter->getValue().getValue<std::vector<foxglove::ParameterValue>>();
357  for (const auto& paramValue : array_params) {
358  int_array_val.push_back(paramValue.getValue<int64_t>());
359  }
360  const std::vector<int64_t> expected_value = {4, 5, 6};
361  EXPECT_EQ(int_array_val, expected_value);
362 }
363 
364 TEST_F(ParameterTest, testSetParametersWithReqId) {
365  const auto p1 = NODE_1_NAME + "." + PARAM_1_NAME;
366  const PARAM_1_TYPE newP1value = "world";
367  const std::vector<foxglove::Parameter> parameters = {
368  foxglove::Parameter(p1, newP1value),
369  };
370 
371  const std::string requestId = "req-testSetParameters";
372  auto future = foxglove::waitForParameters(_wsClient, requestId);
373  _wsClient->setParameters(parameters, requestId);
374  ASSERT_EQ(std::future_status::ready, future.wait_for(DEFAULT_TIMEOUT));
375  std::vector<foxglove::Parameter> params = future.get();
376 
377  EXPECT_EQ(1UL, params.size());
378 }
379 
380 TEST_F(ParameterTest, testUnsetParameter) {
381  const auto p1 = NODE_1_NAME + "." + DELETABLE_PARAM_NAME;
382  const std::vector<foxglove::Parameter> parameters = {
384  };
385 
386  const std::string requestId = "req-testUnsetParameter";
387  auto future = foxglove::waitForParameters(_wsClient, requestId);
388  _wsClient->setParameters(parameters, requestId);
389  ASSERT_EQ(std::future_status::ready, future.wait_for(DEFAULT_TIMEOUT));
390  std::vector<foxglove::Parameter> params = future.get();
391 
392  EXPECT_EQ(0UL, params.size());
393 }
394 
395 TEST_F(ParameterTest, testParameterSubscription) {
396  const auto p1 = NODE_1_NAME + "." + PARAM_1_NAME;
397 
398  _wsClient->subscribeParameterUpdates({p1});
399  auto future = foxglove::waitForParameters(_wsClient);
400  _wsClient->setParameters({foxglove::Parameter(p1, "foo")});
401  ASSERT_EQ(std::future_status::ready, future.wait_for(DEFAULT_TIMEOUT));
402  std::vector<foxglove::Parameter> params = future.get();
403 
404  ASSERT_EQ(1UL, params.size());
405  EXPECT_EQ(params.front().getName(), p1);
406 
407  _wsClient->unsubscribeParameterUpdates({p1});
408  _wsClient->setParameters({foxglove::Parameter(p1, "bar")});
409 
411  ASSERT_EQ(std::future_status::timeout, future.wait_for(ONE_SECOND));
412 }
413 
414 TEST_F(ParameterTest, testGetParametersParallel) {
415  // Connect a few clients (in parallel) and make sure that they all receive parameters
416  auto clients = {
417  std::make_shared<foxglove::Client<websocketpp::config::asio_client>>(),
419  std::make_shared<foxglove::Client<websocketpp::config::asio_client>>(),
420  };
421 
422  std::vector<std::future<std::vector<foxglove::Parameter>>> futures;
423  for (auto client : clients) {
424  futures.push_back(
425  std::async(std::launch::async, [client]() -> std::vector<foxglove::Parameter> {
426  if (std::future_status::ready == client->connect(URI).wait_for(DEFAULT_TIMEOUT)) {
427  const std::string requestId = "req-123";
428  auto future = foxglove::waitForParameters(client, requestId);
429  client->getParameters({}, requestId);
430  future.wait_for(DEFAULT_TIMEOUT);
431  if (future.valid()) {
432  return future.get();
433  }
434  }
435  return {};
436  }));
437  }
438 
439  for (auto& future : futures) {
440  ASSERT_EQ(std::future_status::ready, future.wait_for(DEFAULT_TIMEOUT));
441  std::vector<foxglove::Parameter> parameters;
442  EXPECT_NO_THROW(parameters = future.get());
443  EXPECT_GE(parameters.size(), 2UL);
444  }
445 }
446 
447 TEST_F(ServiceTest, testCallServiceParallel) {
448  // Connect a few clients (in parallel) and make sure that they can all call the service
449  auto clients = {
450  std::make_shared<foxglove::Client<websocketpp::config::asio_client>>(),
452  std::make_shared<foxglove::Client<websocketpp::config::asio_client>>(),
453  };
454 
455  auto serviceFuture = foxglove::waitForService(*clients.begin(), SERVICE_NAME);
456  for (auto client : clients) {
457  ASSERT_EQ(std::future_status::ready, client->connect(URI).wait_for(std::chrono::seconds(5)));
458  }
459  ASSERT_EQ(std::future_status::ready, serviceFuture.wait_for(std::chrono::seconds(5)));
460  const foxglove::Service service = serviceFuture.get();
461 
462  std_srvs::srv::SetBool::Request requestMsg;
463  requestMsg.data = true;
464  const auto serializedRequest = serializeMsg(&requestMsg);
465  const auto& serRequestMsg = serializedRequest->get_rcl_serialized_message();
466 
467  foxglove::ServiceRequest request;
468  request.serviceId = service.id;
469  request.callId = 123lu;
470  request.encoding = "cdr";
471  request.data.resize(serRequestMsg.buffer_length);
472  std::memcpy(request.data.data(), serRequestMsg.buffer, serRequestMsg.buffer_length);
473 
474  std::vector<std::future<foxglove::ServiceResponse>> futures;
475  for (auto client : clients) {
476  futures.push_back(foxglove::waitForServiceResponse(client));
477  client->sendServiceRequest(request);
478  }
479 
480  for (auto& future : futures) {
481  ASSERT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(5)));
483  EXPECT_NO_THROW(response = future.get());
484  EXPECT_EQ(response.serviceId, request.serviceId);
485  EXPECT_EQ(response.callId, request.callId);
486  EXPECT_EQ(response.encoding, request.encoding);
487 
488  rclcpp::SerializedMessage serializedResponseMsg(response.data.size());
489  auto& serMsg = serializedResponseMsg.get_rcl_serialized_message();
490  std::memcpy(serMsg.buffer, response.data.data(), response.data.size());
491  serMsg.buffer_length = response.data.size();
492  const auto resMsg = deserializeMsg<std_srvs::srv::SetBool::Response>(&serMsg);
493 
494  EXPECT_EQ(resMsg->message, "hello");
495  EXPECT_EQ(resMsg->success, requestMsg.data);
496  }
497 }
498 
499 // Run all the tests that were declared with TEST()
500 int main(int argc, char** argv) {
501  testing::InitGoogleTest(&argc, argv);
502  rclcpp::init(argc, argv);
503 
504  const size_t numThreads = 2;
505  auto executor =
506  rclcpp::executors::MultiThreadedExecutor::make_shared(rclcpp::ExecutorOptions{}, numThreads);
507 
508  rclcpp_components::ComponentManager componentManager(executor, "ComponentManager");
509  const auto componentResources = componentManager.get_component_resources("foxglove_bridge");
510 
511  if (componentResources.empty()) {
512  RCLCPP_INFO(componentManager.get_logger(), "No loadable resources found");
513  return EXIT_FAILURE;
514  }
515 
516  auto componentFactory = componentManager.create_component_factory(componentResources.front());
517  auto node = componentFactory->create_node_instance(rclcpp::NodeOptions());
518  executor->add_node(node.get_node_base_interface());
519 
520  std::thread spinnerThread([&executor]() {
521  executor->spin();
522  });
523 
524  const auto testResult = RUN_ALL_TESTS();
525  executor->cancel();
526  spinnerThread.join();
527  rclcpp::shutdown();
528 
529  return testResult;
530 }
constexpr uint8_t HELLO_WORLD_BINARY[]
rclcpp::PublisherBase::SharedPtr _publisher
rclcpp::Node::SharedPtr _paramNode2
bool param(const std::string &param_name, T &param_val, const T &default_val)
rclcpp::executors::SingleThreadedExecutor _executor
static const std::string DELETABLE_PARAM_NAME
static const std::string NODE_2_NAME
std::shared_ptr< foxglove::Client< websocketpp::config::asio_client > > _wsClient
constexpr auto ONE_SECOND
static const PARAM_1_TYPE PARAM_1_DEFAULT_VALUE
constexpr char URI[]
std::future< Service > waitForService(std::shared_ptr< ClientInterface > client, const std::string &serviceName)
Definition: test_client.cpp:97
rclcpp::executors::SingleThreadedExecutor _executor
void advertise(const std::vector< ClientAdvertisement > &channels) override
std::vector< uint8_t > data
Definition: common.hpp:132
std::shared_ptr< T > deserializeMsg(const rcl_serialized_message_t *msg)
TEST(SmokeTest, testConnection)
TEST_F(ExistingPublisherTest, testPublishingWithExistingPublisher)
rclcpp::executors::SingleThreadedExecutor _executor
void connect(const std::string &uri, std::function< void(websocketpp::connection_hdl)> onOpenHandler, std::function< void(websocketpp::connection_hdl)> onCloseHandler=nullptr) override
static const std::string PARAM_2_NAME
constexpr auto DEFAULT_TIMEOUT
void publish(ClientChannelId channelId, const uint8_t *buffer, size_t size) override
void unadvertise(const std::vector< ClientChannelId > &channelIds) override
rclcpp::Node::SharedPtr _paramNode1
std::vector< uint8_t > connectClientAndReceiveMsg(const std::string &uri, const std::string &topic_name)
Definition: test_client.cpp:14
std::shared_ptr< foxglove::Client< websocketpp::config::asio_client > > _wsClient
int main(int argc, char **argv)
static const std::string NODE_1_NAME
static const PARAM_2_TYPE PARAM_2_DEFAULT_VALUE
static const std::string PARAM_1_NAME
ClientChannelId channelId
Definition: common.hpp:76
std::future< ServiceResponse > waitForServiceResponse(std::shared_ptr< ClientInterface > client)
Definition: test_client.cpp:80
std::shared_ptr< rclcpp::SerializedMessage > serializeMsg(const T *msg)
const std::string response
rclcpp::ServiceBase::SharedPtr _service
std::future< std::vector< Parameter > > waitForParameters(std::shared_ptr< ClientInterface > client, const std::string &requestId=std::string())
Definition: test_client.cpp:60


foxglove_bridge
Author(s): Foxglove
autogenerated on Mon Jul 3 2023 02:12:22