gtest_pal_statistics.cpp
Go to the documentation of this file.
1 /*
2  @file
3 
4  @author victor
5 
6  @copyright (c) 2018 PAL Robotics SL. All Rights Reserved
7 */
8 
11 #include <gtest/gtest.h>
12 #include <gmock/gmock.h>
13 #include <ros/ros.h>
14 #include <ros/callback_queue.h>
15 #include <climits>
16 #include <cfloat>
17 
18 using ::testing::UnorderedElementsAre;
19 namespace pal_statistics
20 {
21 class PalStatisticsTest : public ::testing::Test
22 {
23 public:
25  {
26  var1_ = 0.0;
27  var2_ = 0.5;
28  container_.resize(5);
29 
31  sub_ = nh_.subscribe(std::string(DEFAULT_STATISTICS_TOPIC) + "/full", 1, &PalStatisticsTest::fullTopicCb, this);
34  }
35 
36  void fullTopicCb(const pal_statistics_msgs::StatisticsConstPtr &msg)
37  {
38  last_msg_ = msg;
39  }
40  void namesTopicCb(const pal_statistics_msgs::StatisticsNamesConstPtr &msg)
41  {
42  last_names_msg_ = msg;
43  }
44  void valuesTopicCb(const pal_statistics_msgs::StatisticsValuesConstPtr &msg)
45  {
46  last_values_msg_ = msg;
47  }
48  void resetMsgs()
49  {
50  last_msg_.reset();
51  // last names should not be reset, because it's not always published and you'll be using the last one
52  last_values_msg_.reset();
53  }
54  bool waitForMsg(const ros::Duration &timeout)
55  {
56  ros::Time end = ros::Time::now() + timeout;
57  while (ros::Time::now() < end)
58  {
60  ros::Duration(1e-4).sleep();
61  if (last_msg_.get() && last_values_msg_.get())
62  {
63  return true;
64  }
65  }
66  return false;
67  }
68 
69 protected:
70  double var1_;
71  double var2_;
72  std::vector<int> container_;
78  pal_statistics_msgs::StatisticsConstPtr last_msg_;
79  pal_statistics_msgs::StatisticsNamesConstPtr last_names_msg_;
80  pal_statistics_msgs::StatisticsValuesConstPtr last_values_msg_;
81 };
82 
83 
84 std::vector<std::string> getVariables(const pal_statistics_msgs::Statistics &msg)
85 {
86  std::vector<std::string> v;
87  for (const auto &s : msg.statistics)
88  {
89  v.push_back(s.name);
90  }
91  return v;
92 }
93 
94 std::map<std::string, double> getVariableAndValues(const pal_statistics_msgs::Statistics &msg)
95 {
96  std::map<std::string, double> m;
97  for (const auto &s : msg.statistics)
98  {
99  m[s.name] = s.value;
100  }
101  return m;
102 }
103 
105 {
107  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
108  registry->unregisterVariable("foo");
109  customRegister(*registry, "var1", &var1_);
110  customRegister(*registry, "var1", &var1_);
111  registry->unregisterVariable("var1");
112  registry->unregisterVariable("var1");
113 }
114 
116 {
118  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
119 
120  customRegister(*registry, "var1", &var1_);
121  customRegister(*registry, "var2", &var2_);
122 
123  var1_ = 1.0;
124  var2_ = 2.0;
125  pal_statistics_msgs::Statistics msg = registry->createMsg();
126 
127  EXPECT_NEAR(ros::Time::now().toSec(), msg.header.stamp.toSec(), 0.001);
128  auto s = getVariableAndValues(msg);
129  EXPECT_EQ(var1_, s["var1"]);
130  EXPECT_EQ(var2_, s["var2"]);
131 
132  var1_ = 100.0;
133  var2_ = -100.0;
134  msg = registry->createMsg();
135  s = getVariableAndValues(msg);
136  EXPECT_EQ(var1_, s["var1"]);
137  EXPECT_EQ(var2_, s["var2"]);
138 }
139 
141 {
143  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
144 
145 
146  short s = std::numeric_limits<short>::min();
147  const unsigned short us = std::numeric_limits<unsigned short>::max();
148  const char c = std::numeric_limits<char>::min();
149  const unsigned char uc = std::numeric_limits<unsigned char>::max();
150  int i = std::numeric_limits<int>::min();
151  const unsigned int ui = std::numeric_limits<unsigned int>::max();
152  long l = std::numeric_limits<long>::min();
153  const unsigned long ul = std::numeric_limits<long>::max();
154  long long ll = std::numeric_limits<long long>::min();
155  const unsigned long long ull = std::numeric_limits<unsigned long long>::max();
156  float min_f = std::numeric_limits<float>::min();
157  const float max_f = std::numeric_limits<float>::max();
158  const double min_d = std::numeric_limits<double>::min();
159  double max_d = std::numeric_limits<double>::max();
160  bool true_b = true;
161  bool false_b = false;
162 
163 
164 
165  customRegister(*registry, "s", &s);
166  customRegister(*registry, "us", &us);
167  customRegister(*registry, "c", &c);
168  customRegister(*registry, "uc", &uc);
169  customRegister(*registry, "i", &i);
170  customRegister(*registry, "ui", &ui);
171  customRegister(*registry, "l", &l);
172  customRegister(*registry, "ul", &ul);
173  customRegister(*registry, "ll", &ll);
174  customRegister(*registry, "ull", &ull);
175  customRegister(*registry, "min_f", &min_f);
176  customRegister(*registry, "max_f", &max_f);
177  customRegister(*registry, "min_d", &min_d);
178  customRegister(*registry, "max_d", &max_d);
179  customRegister(*registry, "true_b", &true_b);
180  customRegister(*registry, "false_b", &false_b);
181  customRegister(*registry, "container_size", boost::function<size_t ()>(boost::bind(&std::vector<int>::size,
182  &container_)));
183  pal_statistics_msgs::Statistics msg = registry->createMsg();
184 
185  auto values = getVariableAndValues(msg);
186  EXPECT_EQ(s, values["s"]);
187  EXPECT_EQ(us, values["us"]);
188  EXPECT_EQ(c, values["c"]);
189  EXPECT_EQ(uc, values["uc"]);
190  EXPECT_EQ(i, values["i"]);
191  EXPECT_EQ(ui, values["ui"]);
192  EXPECT_EQ(l, values["l"]);
193  EXPECT_EQ(ul, values["ul"]);
194  EXPECT_EQ(ll, values["ll"]);
195  EXPECT_EQ(ull, values["ull"]);
196  EXPECT_EQ(min_f, values["min_f"]);
197  EXPECT_EQ(max_f, values["max_f"]);
198  EXPECT_EQ(min_d, values["min_d"]);
199  EXPECT_EQ(max_d, values["max_d"]);
200  EXPECT_EQ(true_b, values["true_b"]);
201  EXPECT_EQ(false_b, values["false_b"]);
202  EXPECT_EQ(container_.size(), values["container_size"]);
203 
204  EXPECT_NE(l, values["ul"]);
205 }
206 
207 TEST_F(PalStatisticsTest, manualRegistration)
208 {
210  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
211 
212  IdType var1_id = customRegister(*registry, "var1", &var1_);
213  customRegister(*registry, "var2", &var2_);
214  customRegister(*registry, "container_size", boost::function<size_t ()>(boost::bind(&std::vector<int>::size,
215  &container_)));
216 
217  pal_statistics_msgs::Statistics msg = registry->createMsg();
218 
219  EXPECT_NEAR(ros::Time::now().toSec(), msg.header.stamp.toSec(), 0.001);
220  EXPECT_THAT(getVariables(msg),
221  UnorderedElementsAre("var1", "var2", "container_size",
222  "topic_stats.pal_statistics.publish_async_attempts",
223  "topic_stats.pal_statistics.publish_async_failures",
224  "topic_stats.pal_statistics.publish_buffer_full_errors",
225  "topic_stats.pal_statistics.last_async_pub_duration"));
226 
227  registry->unregisterVariable("var2");
228  msg = registry->createMsg();
229  EXPECT_THAT(getVariables(msg),
230  UnorderedElementsAre("var1", "container_size",
231  "topic_stats.pal_statistics.publish_async_attempts",
232  "topic_stats.pal_statistics.publish_async_failures",
233  "topic_stats.pal_statistics.publish_buffer_full_errors",
234  "topic_stats.pal_statistics.last_async_pub_duration"));
235 
236  EXPECT_TRUE(registry->disable(var1_id));
237  msg = registry->createMsg();
238  EXPECT_THAT(getVariables(msg),
239  UnorderedElementsAre("container_size",
240  "topic_stats.pal_statistics.publish_async_attempts",
241  "topic_stats.pal_statistics.publish_async_failures",
242  "topic_stats.pal_statistics.publish_buffer_full_errors",
243  "topic_stats.pal_statistics.last_async_pub_duration"));
244 
245 
246  EXPECT_TRUE(registry->enable(var1_id));
247  msg = registry->createMsg();
248  EXPECT_THAT(getVariables(msg),
249  UnorderedElementsAre("var1", "container_size",
250  "topic_stats.pal_statistics.publish_async_attempts",
251  "topic_stats.pal_statistics.publish_async_failures",
252  "topic_stats.pal_statistics.publish_buffer_full_errors",
253  "topic_stats.pal_statistics.last_async_pub_duration"));
254 }
255 
256 
257 TEST_F(PalStatisticsTest, automaticRegistration)
258 {
260  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
261  pal_statistics_msgs::Statistics msg;
262  {
263  RegistrationsRAII bookkeeping;
264 
265  customRegister(*registry, "var1", &var1_, &bookkeeping);
266  customRegister(*registry, "var2", &var2_, &bookkeeping);
267 
268  msg = registry->createMsg();
269 
270  EXPECT_NEAR(ros::Time::now().toSec(), msg.header.stamp.toSec(), 0.001);
271  EXPECT_THAT(getVariables(msg),
272  UnorderedElementsAre("var1", "var2",
273  "topic_stats.pal_statistics.publish_async_attempts",
274  "topic_stats.pal_statistics.publish_async_failures",
275  "topic_stats.pal_statistics.publish_buffer_full_errors",
276  "topic_stats.pal_statistics.last_async_pub_duration"));
277 
278  EXPECT_TRUE(bookkeeping.disableAll());
279  msg = registry->createMsg();
280  EXPECT_THAT(getVariables(msg),
281  UnorderedElementsAre("topic_stats.pal_statistics.publish_async_attempts",
282  "topic_stats.pal_statistics.publish_async_failures",
283  "topic_stats.pal_statistics.publish_buffer_full_errors",
284  "topic_stats.pal_statistics.last_async_pub_duration"));
285 
286  EXPECT_TRUE(bookkeeping.enableAll());
287  msg = registry->createMsg();
288  EXPECT_THAT(getVariables(msg),
289  UnorderedElementsAre("var1", "var2",
290  "topic_stats.pal_statistics.publish_async_attempts",
291  "topic_stats.pal_statistics.publish_async_failures",
292  "topic_stats.pal_statistics.publish_buffer_full_errors",
293  "topic_stats.pal_statistics.last_async_pub_duration"));
294 
295  }
296 
297  msg = registry->createMsg();
298  EXPECT_THAT(getVariables(msg),
299  UnorderedElementsAre("topic_stats.pal_statistics.publish_async_attempts",
300  "topic_stats.pal_statistics.publish_async_failures",
301  "topic_stats.pal_statistics.publish_buffer_full_errors",
302  "topic_stats.pal_statistics.last_async_pub_duration"));
303 }
304 
305 
306 TEST_F(PalStatisticsTest, automaticRegistrationDestruction)
307 {
309  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
310  {
311  RegistrationsRAII bookkeeping;
312 
313  customRegister(*registry, "var1", &var1_, &bookkeeping);
314  customRegister(*registry, "var2", &var2_, &bookkeeping);
315 
316  registry->createMsg();
317 
318  // Delete the main class, the bookkeeper shouldn't crash on destruction
319  registry.reset();
320  }
321 }
322 
323 TEST_F(PalStatisticsTest, asyncPublisher)
324 {
326  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
327  {
328  RegistrationsRAII bookkeeping;
329 
330  registry->startPublishThread();
331 
332  // Time for publisher to connect to subscriber
333  ros::Duration(0.5).sleep();
334  customRegister(*registry, "var1", &var1_, &bookkeeping);
335  customRegister(*registry, "var2", &var2_, &bookkeeping);
336 
337  registry->publishAsync();
338  ASSERT_TRUE(waitForMsg(ros::Duration(0.3)));
339 
341  EXPECT_EQ(var1_, s["var1"]);
342  EXPECT_EQ(var2_, s["var2"]);
343 
344  last_msg_.reset();
345  ASSERT_FALSE(waitForMsg(ros::Duration(0.3)))
346  << " Data shouldn't have been published because there were no calls to publishAsync";
347 
348  var1_ = 2.0;
349  var2_ = 3.0;
350  registry->publishAsync();
351  ASSERT_TRUE(waitForMsg(ros::Duration(0.3)));
352 
354  EXPECT_EQ(var1_, s["var1"]);
355  EXPECT_EQ(var2_, s["var2"]);
356 
357  last_msg_.reset();
358  }
359  registry->publishAsync();
360  ASSERT_TRUE(waitForMsg(ros::Duration(0.3)));
361  // Number of internal statistics
362  EXPECT_EQ(4, last_msg_->statistics.size());
363 }
364 
366 {
367  {
368  RegistrationsRAII bookkeeping;
369  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "macro_var1", &var1_, NULL);
370  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "macro_var1_bk", &var1_, &bookkeeping);
371  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "macro_var2", &var2_, NULL);
374  // Time for publisher to connect to subscriber
375  ros::Duration(0.5).sleep();
377  ASSERT_TRUE(waitForMsg(ros::Duration(0.3)));
378  EXPECT_THAT(getVariables(*last_msg_),
379  UnorderedElementsAre("macro_var1", "macro_var1_bk", "macro_var2", "&var2_",
380  "topic_stats.pal_statistics.publish_async_attempts",
381  "topic_stats.pal_statistics.publish_async_failures",
382  "topic_stats.pal_statistics.publish_buffer_full_errors",
383  "topic_stats.pal_statistics.last_async_pub_duration"));
384  last_msg_.reset();
385  }
387  ASSERT_TRUE(waitForMsg(ros::Duration(0.3)));
388  EXPECT_THAT(getVariables(*last_msg_),
389  UnorderedElementsAre("macro_var1", "macro_var2",
390  "topic_stats.pal_statistics.publish_async_attempts",
391  "topic_stats.pal_statistics.publish_async_failures",
392  "topic_stats.pal_statistics.publish_buffer_full_errors",
393  "topic_stats.pal_statistics.last_async_pub_duration"));
394  last_msg_.reset();
395 
396  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "macro_var2_bis", &var2_, NULL);
397  UNREGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "macro_var2", NULL);
398  var1_ = 123.456;
400  ASSERT_TRUE(waitForMsg(ros::Duration(0.3)));
401  EXPECT_THAT(getVariables(*last_msg_),
402  UnorderedElementsAre("macro_var1", "macro_var2_bis",
403  "topic_stats.pal_statistics.publish_async_attempts",
404  "topic_stats.pal_statistics.publish_async_failures",
405  "topic_stats.pal_statistics.publish_buffer_full_errors",
406  "topic_stats.pal_statistics.last_async_pub_duration"));
407  EXPECT_EQ(var1_, getVariableAndValues(*last_msg_)["macro_var1"]);
408  UNREGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "macro_var1", NULL);
409  UNREGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "macro_var2_bis", NULL);
410 
411 
412 
413 
414 }
415 
416 void registerThread(boost::shared_ptr<StatisticsRegistry> registry, const std::string &prefix,
417  size_t iterations, double *variable, RegistrationsRAII *bookkeeping = NULL)
418 {
419  for (size_t i = 0; i < iterations; ++i)
420  {
422  customRegister(*registry, prefix + std::to_string(i), variable, bookkeeping);
423  // ROS_INFO_STREAM(i << " " << (ros::Time::now() - b).toSec());
424  }
425 }
427  const std::string &prefix, size_t n_variables)
428 {
429  // Deregister in inverse order
430  for (size_t i = n_variables; i > 0; --i)
431  {
432  registry->unregisterVariable(prefix + std::to_string(i - 1), NULL);
433  }
434 }
435 
436 
437 void publish(boost::shared_ptr<StatisticsRegistry> registry, size_t n_variables)
438 {
439  for (size_t i = n_variables; i > 0; --i)
440  {
441  registry->publish();
442  }
443 }
444 
445 
446 void publishAsync(boost::shared_ptr<StatisticsRegistry> registry, size_t n_variables)
447 {
448  for (size_t i = n_variables; i > 0; --i)
449  {
450  registry->publishAsync();
451  }
452 }
453 
455 {
456  double d = 5.0;
458  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
459  registry->startPublishThread();
460  customRegister(*registry, "test_variable", &d);
461  customRegister(*registry, "test_variable2", &d);
462  size_t received_messages = 0;
463 
464  ros::NodeHandle async_nh;
465  ros::CallbackQueue async_queue;
466  async_nh.setCallbackQueue(&async_queue);
467  ros::AsyncSpinner spinner(1, &async_queue);
468  spinner.start();
469  ros::Subscriber sub = async_nh.subscribe<pal_statistics_msgs::Statistics>(
470  std::string(DEFAULT_STATISTICS_TOPIC) + "/full", 1000000,
471  [&](const pal_statistics_msgs::StatisticsConstPtr &) { received_messages++; });
472  while (sub.getNumPublishers() == 0)
473  {
474  ros::Duration(0.1).sleep();
475  }
476 
477  ros::Rate rate(1e4);
478  size_t num_messages = 3e4;
479  size_t success_async = 0;
480  for (size_t i = 0; i < num_messages; ++i)
481  {
482  success_async += registry->publishAsync();
483  rate.sleep();
484  }
485 
486  //Allow time for everything to arrive
487  ros::Duration(0.5).sleep();
488 
489  EXPECT_EQ(success_async - registry->registration_list_.overwritten_data_count_, received_messages);
490 }
491 
492 TEST_F(PalStatisticsTest, concurrencyTest)
493 {
494  size_t n_threads = 5;
495  size_t n_variables = 2e4/n_threads; //2e4 variables in total
496  std::vector<boost::thread> threads;
498  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
499  registry->startPublishThread();
500  ROS_INFO_STREAM("Start registration threads");
501  for (size_t i = 0; i < n_threads; ++i)
502  {
503  threads.push_back(boost::thread(boost::bind(&registerThread, registry,
504  std::to_string(i) + "_", n_variables, &var1_,
505  static_cast<RegistrationsRAII *>(NULL))));
506  }
507  for (size_t i = 0; i < n_threads; ++i)
508  {
509  threads[i].join();
510  }
511  ROS_INFO_STREAM("Registration ended");
512  pal_statistics_msgs::Statistics msg = registry->createMsg();
513 
514  EXPECT_EQ(4 + n_variables * n_threads, msg.statistics.size());
515  ROS_INFO_STREAM("Start publishAsync");
517  size_t iter = 10000;
518 // ros::Rate rate(1e3);
519  for (size_t i = 0; i < iter; ++i)
520  {
521  registry->publishAsync();
522 // rate.sleep();
523  }
524  // Time to publish 1000 times the registered statistics
525  ROS_INFO_STREAM("End publishAsync " << (1000. * (ros::Time::now() - b).toSec()) / double(iter));
526  ROS_INFO_STREAM("Start publish");
527  for (size_t i = 0; i < n_variables; ++i)
528  {
529  registry->publish();
530  }
531  ROS_INFO_STREAM("End publish");
532 
533  threads.clear();
534  ROS_INFO_STREAM("Start deregistration threads");
535  for (size_t i = 0; i < n_threads; ++i)
536  {
537  threads.push_back(boost::thread(
538  boost::bind(&unregisterThread, registry, std::to_string(i) + "_", n_variables)));
539  }
540  for (size_t i = 0; i < n_threads; ++i)
541  {
542  threads[i].join();
543  }
544  ROS_INFO_STREAM("Deregistration ended");
545  msg = registry->createMsg();
546  threads.clear();
547 
548  // Number of internal variables
549  EXPECT_EQ(4, msg.statistics.size());
550 
551 
552  for (size_t i = 0; i < n_threads; ++i)
553  {
554  threads[i].join();
555  }
556 
557  threads.clear();
558 }
559 
560 TEST_F(PalStatisticsTest, concurrencyMixTest)
561 {
562  size_t n_variables = 2e3;
563  size_t n_threads = 5;
564  std::vector<boost::thread> threads;
566  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
567  for (size_t i = 0; i < n_threads; ++i)
568  {
569  threads.push_back(boost::thread(boost::bind(&registerThread, registry,
570  std::to_string(i) + "_", n_variables, &var1_,
571  static_cast<RegistrationsRAII *>(NULL))));
572  }
573  for (size_t i = 0; i < threads.size(); ++i)
574  {
575  threads[i].join();
576  }
577  threads.clear();
578 
579 
580  ROS_INFO_STREAM("Start thread mix");
581  RegistrationsRAII bookkeeping;
582  for (size_t i = 0; i < n_threads; ++i)
583  {
584  threads.push_back(boost::thread(
585  boost::bind(&unregisterThread, registry, std::to_string(i) + "_", n_variables)));
586  threads.push_back(boost::thread(boost::bind(&registerThread, registry,
587  std::to_string(i + n_threads) + "_",
588  n_variables, &var1_, &bookkeeping)));
589  // threads.push_back(boost::thread(boost::bind(&publish, registry, n_variables)));
590  // threads.push_back(boost::thread(boost::bind(&publishAsync, registry,
591  // n_variables)));
592  }
593  for (size_t i = 0; i < threads.size(); ++i)
594  {
595  threads[i].join();
596  }
597  ROS_INFO_STREAM("End thread mix");
598 }
599 
600 TEST_F(PalStatisticsTest, singlePublish)
601 {
603  boost::make_shared<StatisticsRegistry>(DEFAULT_STATISTICS_TOPIC);
604  double d = 0.123;
605  registry->publishCustomStatistic("single_stat", d);
606 
608  EXPECT_TRUE(last_msg_.get());
609  ASSERT_EQ(1, last_msg_->statistics.size());
610  EXPECT_EQ("single_stat", last_msg_->statistics[0].name);
611  EXPECT_DOUBLE_EQ(d, last_msg_->statistics[0].value);
612 }
613 
614 
615 
617 {
618  // Tests the registration of a variable and publication by the nonrt thread
619  // before a publish_async has been performed
620  RegistrationsRAII bookkeeping;
621  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "var1", &var1_, &bookkeeping);
623  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "var2", &var2_, &bookkeeping);
624  ros::Duration(0.2).sleep();
626  ros::Duration(0.2).sleep();
627 }
628 
630 {
631  // Tests the unregistration of a variable and publication by the nonrt thread
632  // before a publish_async has been performed
633  RegistrationsRAII bookkeeping;
636  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "var2", &var2_, &bookkeeping);
638  ros::Duration(0.2).sleep();
640 
641  last_msg_.reset();
642  ASSERT_TRUE(waitForMsg(ros::Duration(0.3)));
643  EXPECT_THAT(getVariables(*last_msg_),
644  UnorderedElementsAre("var2",
645  "topic_stats.pal_statistics.publish_async_attempts",
646  "topic_stats.pal_statistics.publish_async_failures",
647  "topic_stats.pal_statistics.publish_buffer_full_errors",
648  "topic_stats.pal_statistics.last_async_pub_duration"));
649 }
650 
652 {
653  // Tests the disabling of a variable and publication by the nonrt thread
654  // before a publish_async has been performed
655  RegistrationsRAII bookkeeping;
656  auto var1id = REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "var1", &var1_, nullptr);
658  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "var2", &var2_, &bookkeeping);
659  getRegistry(DEFAULT_STATISTICS_TOPIC)->disable(var1id);
660  ros::Duration(0.2).sleep();
662 
663  last_msg_.reset();
664  ASSERT_TRUE(waitForMsg(ros::Duration(0.3)));
665  EXPECT_THAT(getVariables(*last_msg_),
666  UnorderedElementsAre("var2",
667  "topic_stats.pal_statistics.publish_async_attempts",
668  "topic_stats.pal_statistics.publish_async_failures",
669  "topic_stats.pal_statistics.publish_buffer_full_errors",
670  "topic_stats.pal_statistics.last_async_pub_duration"));
671 }
672 
673 
674 TEST_F(PalStatisticsTest, splitMsgTest)
675 {
676  std::string topic("other_topic");
677  RegistrationsRAII bookkeeping;
678  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "macro_var1", &var1_, NULL);
679  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "macro_var1_bk", &var1_, &bookkeeping);
680  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "macro_var2", &var2_, NULL);
682  // Time for publisher to connect to subscriber
683  ros::Duration(0.2).sleep();
684  unsigned int old_names_version = 0;
685  for (int i = 0; i < 4; ++i)
686  {
687  for (bool remove : {false, true})
688  {
689  if (!remove)
690  {
691  REGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "var" + std::to_string(i), &var2_, NULL);
692  }
693  else
694  {
695  UNREGISTER_VARIABLE(DEFAULT_STATISTICS_TOPIC, "var" + std::to_string(i));
696  }
697  SCOPED_TRACE(std::string("Iteration ") + std::to_string(i) + " remove " +
698  std::to_string(remove));
699 
700  resetMsgs();
702  ASSERT_TRUE(waitForMsg(ros::Duration(0.3)));
703  ASSERT_EQ(last_msg_->header.stamp, last_names_msg_->header.stamp);
704  ASSERT_EQ(last_names_msg_->header.stamp, last_values_msg_->header.stamp);
705  ASSERT_EQ(last_names_msg_->names_version, last_values_msg_->names_version);
706  ASSERT_GT(last_names_msg_->names_version, old_names_version);
707  old_names_version = last_names_msg_->names_version;
708 
709  ASSERT_EQ(getVariables(*last_msg_), last_names_msg_->names);
710 
711  resetMsgs();
713  ASSERT_TRUE(waitForMsg(ros::Duration(0.3)));
714  ASSERT_LT(last_names_msg_->header.stamp, last_values_msg_->header.stamp);
715  ASSERT_EQ(last_names_msg_->names_version, last_values_msg_->names_version);
716  ASSERT_EQ(last_names_msg_->names_version, old_names_version);
717 
718  }
719  }
720 }
721 
722 
723 
724 
725 } // namespace pal_statistics
726 
727 int main(int argc, char **argv)
728 {
729  ros::init(argc, argv, "pal_statistics_test");
730  // first nodehandle created of an app must exist until the end of the life of the node
731  // If not, you'll have funny stuff such as no logs printed
732  ros::NodeHandle nh;
734  testing::InitGoogleTest(&argc, argv);
735  return RUN_ALL_TESTS();
736 }
737 
pal_statistics_msgs::StatisticsValuesConstPtr last_values_msg_
d
Definition: setup.py:6
void publish(boost::shared_ptr< StatisticsRegistry > registry, size_t n_variables)
#define PUBLISH_ASYNC_STATISTICS(TOPIC)
bool waitForMsg(const ros::Duration &timeout)
#define REGISTER_VARIABLE_SIMPLE(TOPIC, VARIABLE, BOOKKEEPING)
void publishAsync(boost::shared_ptr< StatisticsRegistry > registry, size_t n_variables)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
XmlRpcServer s
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
IdType customRegister(StatisticsRegistry &registry, const std::string &name, const T *variable, RegistrationsRAII *bookkeeping=NULL, bool enabled=true)
Default implementation that accepts anything variable that can be casted to a double.
uint32_t getNumPublishers() const
void registerThread(boost::shared_ptr< StatisticsRegistry > registry, const std::string &prefix, size_t iterations, double *variable, RegistrationsRAII *bookkeeping=NULL)
#define UNREGISTER_VARIABLE(...)
boost::shared_ptr< StatisticsRegistry > getRegistry(const std::string &topic)
constexpr char DEFAULT_STATISTICS_TOPIC[]
void setCallbackQueue(CallbackQueueInterface *queue)
#define REGISTER_VARIABLE(...)
std::map< std::string, double > getVariableAndValues(const pal_statistics_msgs::Statistics &msg)
bool sleep()
pal_statistics_msgs::StatisticsNamesConstPtr last_names_msg_
#define START_PUBLISH_THREAD(TOPIC)
#define PUBLISH_STATISTICS(TOPIC)
std::vector< std::string > getVariables(const pal_statistics_msgs::Statistics &msg)
The RegistrationsRAII class holds handles to registered variables and when it is destroyed, unregisters them automatically.
#define ROS_INFO_STREAM(args)
int main(int argc, char **argv)
TEST_F(PalStatisticsTest, misUse)
void fullTopicCb(const pal_statistics_msgs::StatisticsConstPtr &msg)
static Time now()
pal_statistics_msgs::StatisticsConstPtr last_msg_
void namesTopicCb(const pal_statistics_msgs::StatisticsNamesConstPtr &msg)
void unregisterThread(boost::shared_ptr< StatisticsRegistry > registry, const std::string &prefix, size_t n_variables)
bool sleep() const
void valuesTopicCb(const pal_statistics_msgs::StatisticsValuesConstPtr &msg)
static bool waitForValid()


pal_statistics
Author(s):
autogenerated on Mon Feb 28 2022 23:04:05