test_shape_shifter.cpp
Go to the documentation of this file.
1 
9 #include "gtest/gtest.h"
10 
11 #include <string>
12 #include <utility>
13 #include <vector>
14 
15 #include <ros/serialization.h>
16 
18 #include <std_msgs/Bool.h>
19 #include <std_msgs/Header.h>
20 #include <std_msgs/String.h>
21 #include <geometry_msgs/Point.h>
22 #include <geometry_msgs/PointStamped.h>
23 
24 TEST(ShapeShifter, MsgToShapeShifter) // NOLINT
25 {
26  // Create a message
27  geometry_msgs::PointStamped msg;
28  msg.header.stamp.sec = 1;
29  msg.header.stamp.nsec = 2;
30  msg.header.frame_id = "test";
31  msg.point.x = 1;
32  msg.point.y = 2;
33  msg.point.z = 3;
34 
35  // Load the message into the shape shifter object
37  cras::msgToShapeShifter(msg, shifter);
38 
39  ASSERT_NO_THROW(shifter.instantiate<geometry_msgs::PointStamped>());
40  const auto msg2 = *shifter.instantiate<geometry_msgs::PointStamped>();
41 
43  cras::msgToShapeShifter(msg2, shifter2);
44 
45  ASSERT_NO_THROW(shifter2.instantiate<geometry_msgs::PointStamped>());
46  const auto msg3 = *shifter2.instantiate<geometry_msgs::PointStamped>();
47 
48  ASSERT_EQ(cras::getBufferLength(shifter), cras::getBufferLength(shifter2));
49 
50  // Compare shifter buffers
51  for (size_t i = 0; i < cras::getBufferLength(shifter); ++i)
52  EXPECT_EQ(cras::getBuffer(shifter2)[i], cras::getBuffer(shifter)[i]);
53 
54  // Compare messages
55  EXPECT_EQ(msg, msg2);
56  EXPECT_EQ(msg, msg3);
57  EXPECT_EQ(msg2, msg3);
58 }
59 
60 TEST(ShapeShifter, GetBuffer) // NOLINT
61 {
62  // Create a message
63  geometry_msgs::PointStamped msg;
64  msg.header.stamp.sec = 1;
65  msg.header.stamp.nsec = 2;
66  msg.header.frame_id = "test";
67  msg.point.x = 1;
68  msg.point.y = 2;
69  msg.point.z = 3;
70 
71  // Load the message into the shape shifter object
73  cras::msgToShapeShifter(msg, shifter);
74 
76  std::vector<uint8_t> buf;
77  buf.resize(length);
78  ros::serialization::OStream ostream(buf.data(), length);
80 
81  // Compare getBuffer() contents with the contents of the byte buffer
82  EXPECT_EQ(length, cras::getBufferLength(shifter));
83  for (size_t i = 0; i < length; ++i)
84  EXPECT_EQ(buf[i], cras::getBuffer(shifter)[i]);
85 
86  // Just verify that we have loaded the buffer into the shape shifter correctly by round-tripping the message
87  EXPECT_EQ(msg, *shifter.instantiate<geometry_msgs::PointStamped>());
88 }
89 
90 TEST(ShapeShifter, GetHeaderPointStamped) // NOLINT
91 {
92  // Create a message
93  geometry_msgs::PointStamped msg;
94  msg.header.stamp.sec = 1;
95  msg.header.stamp.nsec = 2;
96  msg.header.frame_id = "test";
97  msg.point.x = 1;
98  msg.point.y = 2;
99  msg.point.z = 3;
100 
101  // Load the message into the shape shifter object
103  cras::msgToShapeShifter(msg, shifter);
104 
105  EXPECT_TRUE(cras::hasHeader(shifter));
106 
107  auto header = cras::getHeader(shifter);
108  ASSERT_TRUE(header.has_value());
109  EXPECT_EQ(msg.header, header.value());
110 }
111 
112 TEST(ShapeShifter, GetHeaderPoint) // NOLINT
113 {
114  // Create a message
115  geometry_msgs::Point msg;
116  msg.x = 1;
117  msg.y = 2;
118  msg.z = 3;
119 
120  // Load the message into the shape shifter object
122  cras::msgToShapeShifter(msg, shifter);
123 
124  EXPECT_FALSE(cras::hasHeader(shifter));
125 
126  // Do not try to run this as it could segfault
127  // auto header = cras::getHeader(shifter);
128  // ASSERT_TRUE(header.has_value());
129  // EXPECT_EQ(msg, header.value());
130 }
131 
132 TEST(ShapeShifter, GetHeaderFromHeader) // NOLINT
133 {
134  // Create a message
135  std_msgs::Header msg;
136  msg.stamp.sec = 1;
137  msg.stamp.nsec = 2;
138  msg.frame_id = "test";
139 
140  // Load the message into the shape shifter object
142  cras::msgToShapeShifter(msg, shifter);
143 
144  EXPECT_FALSE(cras::hasHeader(shifter));
145 
146  auto header = cras::getHeader(shifter);
147  ASSERT_TRUE(header.has_value());
148  EXPECT_EQ(msg, header.value());
149 }
150 
151 TEST(ShapeShifter, GetHeaderFromBool) // NOLINT
152 {
153  // Create a message
154  std_msgs::Bool msg;
155  msg.data = true;
156 
157  // Load the message into the shape shifter object
159  cras::msgToShapeShifter(msg, shifter);
160 
161  EXPECT_FALSE(cras::hasHeader(shifter));
162 
163  auto header = cras::getHeader(shifter);
164  EXPECT_FALSE(header.has_value());
165 }
166 
167 TEST(ShapeShifter, GetHeaderFromLongString) // NOLINT
168 {
169  // Create a message
170  std_msgs::String msg;
171  msg.data = "123456789012345678901234567890";
172 
173  // Load the message into the shape shifter object
175  cras::msgToShapeShifter(msg, shifter);
176 
177  EXPECT_FALSE(cras::hasHeader(shifter));
178 
179  auto header = cras::getHeader(shifter);
180  EXPECT_FALSE(header.has_value());
181 }
182 
183 TEST(ShapeShifter, GetHeaderFromFakeString) // NOLINT
184 {
185  // Create a message
186  std_msgs::String msg;
187  msg.data = std::string(22, '\x00');
188 
189  // Load the message into the shape shifter object
191  cras::msgToShapeShifter(msg, shifter);
192 
193  EXPECT_FALSE(cras::hasHeader(shifter));
194 
195  auto header = cras::getHeader(shifter);
196  ASSERT_TRUE(header.has_value()); // The string decodes as a Header with seq == length of msg.data
197  std_msgs::Header fakeHeader;
198  fakeHeader.seq = msg.data.size();
199  EXPECT_EQ(fakeHeader, header.value());
200 }
201 
202 TEST(ShapeShifter, SetHeaderSameLength) // NOLINT
203 {
204  // Create a message
205  geometry_msgs::PointStamped msg;
206  msg.header.stamp.sec = 1;
207  msg.header.stamp.nsec = 2;
208  msg.header.frame_id = "test";
209  msg.point.x = 1;
210  msg.point.y = 2;
211  msg.point.z = 3;
212  const auto origMsg = msg;
213 
214  // Load the message into the shape shifter object
216  cras::msgToShapeShifter(msg, shifter);
217 
218  auto newHeader = msg.header;
219  newHeader.frame_id = "abcd";
220  EXPECT_TRUE(cras::setHeader(shifter, newHeader));
221 
222  const auto decodedHeader = cras::getHeader(shifter);
223  ASSERT_TRUE(decodedHeader.has_value());
224  EXPECT_EQ(newHeader, decodedHeader.value());
225 
226  const auto newMsg = shifter.instantiate<geometry_msgs::PointStamped>();
227  EXPECT_EQ(newHeader, newMsg->header);
228  EXPECT_EQ(origMsg.point, newMsg->point);
229 }
230 
231 TEST(ShapeShifter, SetHeaderShorter) // NOLINT
232 {
233  // Create a message
234  geometry_msgs::PointStamped msg;
235  msg.header.stamp.sec = 1;
236  msg.header.stamp.nsec = 2;
237  msg.header.frame_id = "test";
238  msg.point.x = 1;
239  msg.point.y = 2;
240  msg.point.z = 3;
241  const auto origMsg = msg;
242 
243  // Load the message into the shape shifter object
245  cras::msgToShapeShifter(msg, shifter);
246 
247  auto newHeader = msg.header;
248  newHeader.frame_id = "ab";
249  EXPECT_TRUE(cras::setHeader(shifter, newHeader));
250 
251  const auto decodedHeader = cras::getHeader(shifter);
252  ASSERT_TRUE(decodedHeader.has_value());
253  EXPECT_EQ(newHeader, decodedHeader.value());
254 
255  const auto newMsg = shifter.instantiate<geometry_msgs::PointStamped>();
256  EXPECT_EQ(newHeader, newMsg->header);
257  EXPECT_EQ(origMsg.point, newMsg->point);
258 }
259 
260 TEST(ShapeShifter, SetHeaderLonger) // NOLINT
261 {
262  // Create a message
263  geometry_msgs::PointStamped msg;
264  msg.header.stamp.sec = 1;
265  msg.header.stamp.nsec = 2;
266  msg.header.frame_id = "test";
267  msg.point.x = 1;
268  msg.point.y = 2;
269  msg.point.z = 3;
270  const auto origMsg = msg;
271 
272  // Load the message into the shape shifter object
274  cras::msgToShapeShifter(msg, shifter);
275 
276  auto newHeader = msg.header;
277  newHeader.frame_id = "abcdefgh";
278  EXPECT_TRUE(cras::setHeader(shifter, newHeader));
279 
280  const auto decodedHeader = cras::getHeader(shifter);
281  ASSERT_TRUE(decodedHeader.has_value());
282  EXPECT_EQ(newHeader, decodedHeader.value());
283 
284  const auto newMsg = shifter.instantiate<geometry_msgs::PointStamped>();
285  EXPECT_EQ(newHeader, newMsg->header);
286  EXPECT_EQ(origMsg.point, newMsg->point);
287 }
288 
289 TEST(ShapeShifter, CopyShapeShifter) // NOLINT
290 {
291  // Create a message
292  geometry_msgs::PointStamped msg;
293  msg.header.stamp.sec = 1;
294  msg.header.stamp.nsec = 2;
295  msg.header.frame_id = "test";
296  msg.point.x = 1;
297  msg.point.y = 2;
298  msg.point.z = 3;
299  const auto origMsg = msg;
300 
301  // Load the message into the shape shifter object
303  cras::msgToShapeShifter(msg, shifter);
304 
305  topic_tools::ShapeShifter shifter2;
306  // If we used shifter2 = shifter, we'd get a segfault in Melodic when this function ends
307  cras::copyShapeShifter(shifter, shifter2);
308 
309  EXPECT_EQ(*shifter.instantiate<geometry_msgs::PointStamped>(), *shifter2.instantiate<geometry_msgs::PointStamped>());
310  EXPECT_NE(cras::getBuffer(shifter), cras::getBuffer(shifter2));
311 }
312 
313 TEST(ShapeShifter, CopyCrasShapeShifter) // NOLINT
314 {
315  // Create a message
316  geometry_msgs::PointStamped msg;
317  msg.header.stamp.sec = 1;
318  msg.header.stamp.nsec = 2;
319  msg.header.frame_id = "test";
320  msg.point.x = 1;
321  msg.point.y = 2;
322  msg.point.z = 3;
323  const auto origMsg = msg;
324 
325  // Load the message into the shape shifter object
327  cras::msgToShapeShifter(msg, shifter);
328 
329  cras::ShapeShifter shifter2;
330  // With normal ShapeShifter, we'd get a segfault in Melodic when this function ends
331  shifter2 = shifter;
332 
333  EXPECT_EQ(*shifter.instantiate<geometry_msgs::PointStamped>(), *shifter2.instantiate<geometry_msgs::PointStamped>());
334  EXPECT_NE(cras::getBuffer(shifter), cras::getBuffer(shifter2));
335 
336  cras::ShapeShifter shifter3;
337  shifter3 = std::move(shifter2);
338 
339  EXPECT_EQ(*shifter.instantiate<geometry_msgs::PointStamped>(), *shifter3.instantiate<geometry_msgs::PointStamped>());
340  EXPECT_NE(cras::getBuffer(shifter), cras::getBuffer(shifter3));
341 }
342 
343 TEST(ShapeShifter, MessageTraits) // NOLINT
344 {
345  // Create a message
346  geometry_msgs::PointStamped msg;
347  msg.header.stamp.sec = 1;
348  msg.header.stamp.nsec = 2;
349  msg.header.frame_id = "test";
350  msg.point.x = 1;
351  msg.point.y = 2;
352  msg.point.z = 3;
353 
354  // Load the message into the shape shifter object
356  cras::msgToShapeShifter(msg, shifter);
357 
358  namespace mt = ros::message_traits;
359 
360  EXPECT_STREQ(mt::datatype(msg), mt::datatype(shifter));
361  EXPECT_STREQ(mt::definition(msg), mt::definition(shifter));
362  EXPECT_STREQ(mt::md5sum(msg), mt::md5sum(shifter));
363  // We need to use the + trick so that we don't get undefined reference errors
364  // https://stackoverflow.com/a/46296720/1076564
365  EXPECT_EQ(true, +mt::IsMessage<cras::ShapeShifter>::value);
366  EXPECT_EQ(false, +mt::IsSimple<cras::ShapeShifter>::value);
367  EXPECT_EQ(false, +mt::IsFixedSize<cras::ShapeShifter>::value);
368  EXPECT_EQ(false, +mt::HasHeader<cras::ShapeShifter>::value);
369 }
370 
371 int main(int argc, char **argv)
372 {
373  testing::InitGoogleTest(&argc, argv);
374  return RUN_ALL_TESTS();
375 }
ros::serialization::OStream
msg
msg
cras::hasHeader
bool hasHeader(const ::topic_tools::ShapeShifter &msg)
Tell whether the given message has header field.
shape_shifter.h
Tools for more convenient working with ShapeShifter objects.
ros::serialization::serializationLength
uint32_t serializationLength(const boost::array< T, N > &t)
cras::ShapeShifter
ShapeShifter class with fixed behavior on copy/move on Melodic. Use this class everywhere possible to...
Definition: shape_shifter.h:117
ros::message_traits
topic_tools::ShapeShifter::instantiate
boost::shared_ptr< M > instantiate() const
serialization.h
cras::getBufferLength
size_t getBufferLength(const ::topic_tools::ShapeShifter &msg)
Get the length of the internal buffer with serialized message data.
cras::copyShapeShifter
void copyShapeShifter(const ::topic_tools::ShapeShifter &in, ::topic_tools::ShapeShifter &out)
Copy in ShapeShifter to out.
TEST
TEST(ShapeShifter, MsgToShapeShifter)
Definition: test_shape_shifter.cpp:24
cras::msgToShapeShifter
void msgToShapeShifter(const T &msg, ::topic_tools::ShapeShifter &shifter)
Copy the message instance into the given ShapeShifter.
Definition: shape_shifter.hpp:22
length
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
cras::getBuffer
uint8_t * getBuffer(::topic_tools::ShapeShifter &msg)
Get the internal buffer with serialized message data.
topic_tools::ShapeShifter
header
const std::string header
main
int main(int argc, char **argv)
Definition: test_shape_shifter.cpp:371
ros::serialization::serialize
void serialize(Stream &stream, const boost::array< T, N > &t)
cras::getHeader
::cras::optional<::std_msgs::Header > getHeader(const ::topic_tools::ShapeShifter &msg)
Get the header field of the given message, if it has any.
cras::setHeader
bool setHeader(::topic_tools::ShapeShifter &msg, ::std_msgs::Header &header)
Change the header field of the given message, if it has any.


cras_topic_tools
Author(s): Martin Pecka
autogenerated on Sun Mar 2 2025 03:51:09