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/PointStamped.h>
22 
23 TEST(ShapeShifter, MsgToShapeShifter) // NOLINT
24 {
25  // Create a message
26  geometry_msgs::PointStamped msg;
27  msg.header.stamp.sec = 1;
28  msg.header.stamp.nsec = 2;
29  msg.header.frame_id = "test";
30  msg.point.x = 1;
31  msg.point.y = 2;
32  msg.point.z = 3;
33 
34  // Load the message into the shape shifter object
36  cras::msgToShapeShifter(msg, shifter);
37 
38  ASSERT_NO_THROW(shifter.instantiate<geometry_msgs::PointStamped>());
39  const auto msg2 = *shifter.instantiate<geometry_msgs::PointStamped>();
40 
42  cras::msgToShapeShifter(msg2, shifter2);
43 
44  ASSERT_NO_THROW(shifter2.instantiate<geometry_msgs::PointStamped>());
45  const auto msg3 = *shifter2.instantiate<geometry_msgs::PointStamped>();
46 
47  ASSERT_EQ(cras::getBufferLength(shifter), cras::getBufferLength(shifter2));
48 
49  // Compare shifter buffers
50  for (size_t i = 0; i < cras::getBufferLength(shifter); ++i)
51  EXPECT_EQ(cras::getBuffer(shifter2)[i], cras::getBuffer(shifter)[i]);
52 
53  // Compare messages
54  EXPECT_EQ(msg, msg2);
55  EXPECT_EQ(msg, msg3);
56  EXPECT_EQ(msg2, msg3);
57 }
58 
59 TEST(ShapeShifter, GetBuffer) // NOLINT
60 {
61  // Create a message
62  geometry_msgs::PointStamped msg;
63  msg.header.stamp.sec = 1;
64  msg.header.stamp.nsec = 2;
65  msg.header.frame_id = "test";
66  msg.point.x = 1;
67  msg.point.y = 2;
68  msg.point.z = 3;
69 
70  // Load the message into the shape shifter object
72  cras::msgToShapeShifter(msg, shifter);
73 
75  std::vector<uint8_t> buf;
76  buf.resize(length);
77  ros::serialization::OStream ostream(buf.data(), length);
78  ros::serialization::serialize(ostream, msg);
79 
80  // Compare getBuffer() contents with the contents of the byte buffer
81  EXPECT_EQ(length, cras::getBufferLength(shifter));
82  for (size_t i = 0; i < length; ++i)
83  EXPECT_EQ(buf[i], cras::getBuffer(shifter)[i]);
84 
85  // Just verify that we have loaded the buffer into the shape shifter correctly by round-tripping the message
86  EXPECT_EQ(msg, *shifter.instantiate<geometry_msgs::PointStamped>());
87 }
88 
89 TEST(ShapeShifter, GetHeaderOK) // NOLINT
90 {
91  // Create a message
92  geometry_msgs::PointStamped msg;
93  msg.header.stamp.sec = 1;
94  msg.header.stamp.nsec = 2;
95  msg.header.frame_id = "test";
96  msg.point.x = 1;
97  msg.point.y = 2;
98  msg.point.z = 3;
99 
100  // Load the message into the shape shifter object
102  cras::msgToShapeShifter(msg, shifter);
103 
104  auto header = cras::getHeader(shifter);
105  ASSERT_TRUE(header.has_value());
106  EXPECT_EQ(msg.header, header.value());
107 }
108 
109 TEST(ShapeShifter, GetHeaderFromHeader) // NOLINT
110 {
111  // Create a message
112  std_msgs::Header msg;
113  msg.stamp.sec = 1;
114  msg.stamp.nsec = 2;
115  msg.frame_id = "test";
116 
117  // Load the message into the shape shifter object
119  cras::msgToShapeShifter(msg, shifter);
120 
121  auto header = cras::getHeader(shifter);
122  ASSERT_TRUE(header.has_value());
123  EXPECT_EQ(msg, header.value());
124 }
125 
126 TEST(ShapeShifter, GetHeaderFromBool) // NOLINT
127 {
128  // Create a message
129  std_msgs::Bool msg;
130  msg.data = true;
131 
132  // Load the message into the shape shifter object
134  cras::msgToShapeShifter(msg, shifter);
135 
136  auto header = cras::getHeader(shifter);
137  EXPECT_FALSE(header.has_value());
138 }
139 
140 TEST(ShapeShifter, GetHeaderFromLongString) // NOLINT
141 {
142  // Create a message
143  std_msgs::String msg;
144  msg.data = "123456789012345678901234567890";
145 
146  // Load the message into the shape shifter object
148  cras::msgToShapeShifter(msg, shifter);
149 
150  auto header = cras::getHeader(shifter);
151  EXPECT_FALSE(header.has_value());
152 }
153 
154 TEST(ShapeShifter, GetHeaderFromFakeString) // NOLINT
155 {
156  // Create a message
157  std_msgs::String msg;
158  msg.data = std::string(22, '\x00');
159 
160  // Load the message into the shape shifter object
162  cras::msgToShapeShifter(msg, shifter);
163 
164  auto header = cras::getHeader(shifter);
165  ASSERT_TRUE(header.has_value()); // The string decodes as a Header with seq == length of msg.data
166  std_msgs::Header fakeHeader;
167  fakeHeader.seq = msg.data.size();
168  EXPECT_EQ(fakeHeader, header.value());
169 }
170 
171 TEST(ShapeShifter, SetHeaderSameLength) // NOLINT
172 {
173  // Create a message
174  geometry_msgs::PointStamped msg;
175  msg.header.stamp.sec = 1;
176  msg.header.stamp.nsec = 2;
177  msg.header.frame_id = "test";
178  msg.point.x = 1;
179  msg.point.y = 2;
180  msg.point.z = 3;
181  const auto origMsg = msg;
182 
183  // Load the message into the shape shifter object
185  cras::msgToShapeShifter(msg, shifter);
186 
187  auto newHeader = msg.header;
188  newHeader.frame_id = "abcd";
189  EXPECT_TRUE(cras::setHeader(shifter, newHeader));
190 
191  const auto decodedHeader = cras::getHeader(shifter);
192  ASSERT_TRUE(decodedHeader.has_value());
193  EXPECT_EQ(newHeader, decodedHeader.value());
194 
195  const auto newMsg = shifter.instantiate<geometry_msgs::PointStamped>();
196  EXPECT_EQ(newHeader, newMsg->header);
197  EXPECT_EQ(origMsg.point, newMsg->point);
198 }
199 
200 TEST(ShapeShifter, SetHeaderShorter) // NOLINT
201 {
202  // Create a message
203  geometry_msgs::PointStamped msg;
204  msg.header.stamp.sec = 1;
205  msg.header.stamp.nsec = 2;
206  msg.header.frame_id = "test";
207  msg.point.x = 1;
208  msg.point.y = 2;
209  msg.point.z = 3;
210  const auto origMsg = msg;
211 
212  // Load the message into the shape shifter object
214  cras::msgToShapeShifter(msg, shifter);
215 
216  auto newHeader = msg.header;
217  newHeader.frame_id = "ab";
218  EXPECT_TRUE(cras::setHeader(shifter, newHeader));
219 
220  const auto decodedHeader = cras::getHeader(shifter);
221  ASSERT_TRUE(decodedHeader.has_value());
222  EXPECT_EQ(newHeader, decodedHeader.value());
223 
224  const auto newMsg = shifter.instantiate<geometry_msgs::PointStamped>();
225  EXPECT_EQ(newHeader, newMsg->header);
226  EXPECT_EQ(origMsg.point, newMsg->point);
227 }
228 
229 TEST(ShapeShifter, SetHeaderLonger) // NOLINT
230 {
231  // Create a message
232  geometry_msgs::PointStamped msg;
233  msg.header.stamp.sec = 1;
234  msg.header.stamp.nsec = 2;
235  msg.header.frame_id = "test";
236  msg.point.x = 1;
237  msg.point.y = 2;
238  msg.point.z = 3;
239  const auto origMsg = msg;
240 
241  // Load the message into the shape shifter object
243  cras::msgToShapeShifter(msg, shifter);
244 
245  auto newHeader = msg.header;
246  newHeader.frame_id = "abcdefgh";
247  EXPECT_TRUE(cras::setHeader(shifter, newHeader));
248 
249  const auto decodedHeader = cras::getHeader(shifter);
250  ASSERT_TRUE(decodedHeader.has_value());
251  EXPECT_EQ(newHeader, decodedHeader.value());
252 
253  const auto newMsg = shifter.instantiate<geometry_msgs::PointStamped>();
254  EXPECT_EQ(newHeader, newMsg->header);
255  EXPECT_EQ(origMsg.point, newMsg->point);
256 }
257 
258 TEST(ShapeShifter, CopyShapeShifter) // NOLINT
259 {
260  // Create a message
261  geometry_msgs::PointStamped msg;
262  msg.header.stamp.sec = 1;
263  msg.header.stamp.nsec = 2;
264  msg.header.frame_id = "test";
265  msg.point.x = 1;
266  msg.point.y = 2;
267  msg.point.z = 3;
268  const auto origMsg = msg;
269 
270  // Load the message into the shape shifter object
272  cras::msgToShapeShifter(msg, shifter);
273 
274  topic_tools::ShapeShifter shifter2;
275  // If we used shifter2 = shifter, we'd get a segfault in Melodic when this function ends
276  cras::copyShapeShifter(shifter, shifter2);
277 
278  EXPECT_EQ(*shifter.instantiate<geometry_msgs::PointStamped>(), *shifter2.instantiate<geometry_msgs::PointStamped>());
279  EXPECT_NE(cras::getBuffer(shifter), cras::getBuffer(shifter2));
280 }
281 
282 TEST(ShapeShifter, CopyCrasShapeShifter) // NOLINT
283 {
284  // Create a message
285  geometry_msgs::PointStamped msg;
286  msg.header.stamp.sec = 1;
287  msg.header.stamp.nsec = 2;
288  msg.header.frame_id = "test";
289  msg.point.x = 1;
290  msg.point.y = 2;
291  msg.point.z = 3;
292  const auto origMsg = msg;
293 
294  // Load the message into the shape shifter object
296  cras::msgToShapeShifter(msg, shifter);
297 
298  cras::ShapeShifter shifter2;
299  // With normal ShapeShifter, we'd get a segfault in Melodic when this function ends
300  shifter2 = shifter;
301 
302  EXPECT_EQ(*shifter.instantiate<geometry_msgs::PointStamped>(), *shifter2.instantiate<geometry_msgs::PointStamped>());
303  EXPECT_NE(cras::getBuffer(shifter), cras::getBuffer(shifter2));
304 
305  cras::ShapeShifter shifter3;
306  shifter3 = std::move(shifter2);
307 
308  EXPECT_EQ(*shifter.instantiate<geometry_msgs::PointStamped>(), *shifter3.instantiate<geometry_msgs::PointStamped>());
309  EXPECT_NE(cras::getBuffer(shifter), cras::getBuffer(shifter3));
310 }
311 
312 int main(int argc, char **argv)
313 {
314  testing::InitGoogleTest(&argc, argv);
315  return RUN_ALL_TESTS();
316 }
msg
void copyShapeShifter(const ::topic_tools::ShapeShifter &in, ::topic_tools::ShapeShifter &out)
Copy in ShapeShifter to out.
uint8_t * getBuffer(::topic_tools::ShapeShifter &msg)
Get the internal buffer with serialized message data.
::cras::optional<::std_msgs::Header > getHeader(const ::topic_tools::ShapeShifter &msg)
Get the header field of the given message, if it has any.
void msgToShapeShifter(const T &msg, ::topic_tools::ShapeShifter &shifter)
Copy the message instance into the given ShapeShifter.
void serialize(Stream &stream, const T &t)
Tools for more convenient working with ShapeShifter objects.
bool setHeader(::topic_tools::ShapeShifter &msg, ::std_msgs::Header &header)
Change the header field of the given message, if it has any.
TEST(ShapeShifter, MsgToShapeShifter)
size_t getBufferLength(const ::topic_tools::ShapeShifter &msg)
Get the length of the internal buffer with serialized message data.
uint32_t serializationLength(const T &t)
ShapeShifter class with fixed behavior on copy/move on Melodic. Use this class everywhere possible to...
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
const std::string header
int main(int argc, char **argv)
boost::shared_ptr< M > instantiate() const


cras_topic_tools
Author(s): Martin Pecka
autogenerated on Sat Jun 17 2023 02:33:13