test_unique_id.cpp
Go to the documentation of this file.
1 //
2 // C++ unit tests for unique_id interface.
3 //
4 #include <gtest/gtest.h>
5 
6 #include <ros/ros.h>
7 #include <unique_id/unique_id.h>
8 
9 using namespace unique_id;
12 
14 // Test cases
16 
17 // Test random generator
18 TEST(BoostUUID, fromRandom)
19 {
20  static const int N = 1000;
21  uuid uu[N];
22  for (int i = 0; i < N; ++i)
23  {
24  uu[i] = fromRandom();
25  for (int j = i-1; j >= 0; --j)
26  {
27  EXPECT_NE(uu[i], uu[j]);
28  }
29  }
30 }
31 
32 // Test Timebased UUID
33 TEST(BoostUUID, fromTime)
34 {
35  ros::Time t(1515778146, 239216089);
36  uint64_t hw_addr = 0xAABBCCDDEEFF;
37 
38  // Generate UUID from time and hardware address
39  uuid uu = fromTime(t, hw_addr);
40 
41  // Obtain time since epoch back from the generated uuid
42  std::vector<uint8_t> data(uu.size());
43  std::copy(uu.begin(), uu.end(), data.begin());
44 
45  uint64_t timestamp = (static_cast<uint64_t>(data[0]) << 24) + (static_cast<uint64_t>(data[1]) << 16) +
46  (static_cast<uint64_t>(data[2]) << 8) + static_cast<uint64_t>(data[3]) +
47  (static_cast<uint64_t>(data[4]) << 40) + (static_cast<uint64_t>(data[5]) << 32) +
48  (static_cast<uint64_t>(data[6] & 0x0F) << 56) + (static_cast<uint64_t>(data[7]) << 48);
49  uint64_t offset = 122192928000000000; // time offset in 100 ns intervals between RFC4122 Timestamp and Epoch Time
50  uint64_t ns_intervals = timestamp - offset;
51  uint64_t uu_hw_addr = 0;
52  for (int8_t i=0; i < 6; i++)
53  {
54  uu_hw_addr += static_cast<uint64_t>(data[uu.size() - 1 - i]) << 8*i;
55  }
56 
57  ros::Time uu_time;
58  uu_time.sec = static_cast<int32_t>(ns_intervals / 1e9 * 100);
59  uu_time.nsec = static_cast<int32_t>((ns_intervals - static_cast<uint64_t>(uu_time.sec) / (100 * 1e-9)) * 100);
60 
61  EXPECT_EQ(t.sec, uu_time.sec);
62  // The UUID stores the timestamp in 100ns intervals,
63  // so we lose precision for the 1's and 10's value of the nanoseconds in the time given
64  EXPECT_EQ(t.nsec - uu_time.nsec, 89);
65  EXPECT_EQ(hw_addr, uu_hw_addr);
66 }
67 
68 TEST(BoostUUID, timeWithinSameInterval)
69 {
70  ros::Time t1(1515778146, 239216020);
71  ros::Time t2(1515778146, 239216080);
72  uint64_t hw_addr = 0xAABBCCDDEEFF;
73 
74  // Generate UUIDs from times and hardware address
75  uuid uu1 = fromTime(t1, hw_addr);
76  uuid uu2 = fromTime(t2, hw_addr);
77 
78  // Obtain times since epoch back from uu1
79  std::vector<uint8_t> data(uu1.size());
80  std::copy(uu1.begin(), uu1.end(), data.begin());
81 
82  uint64_t timestamp = (static_cast<uint64_t>(data[0]) << 24) + (static_cast<uint64_t>(data[1]) << 16) +
83  (static_cast<uint64_t>(data[2]) << 8) + static_cast<uint64_t>(data[3]) +
84  (static_cast<uint64_t>(data[4]) << 40) + (static_cast<uint64_t>(data[5]) << 32) +
85  (static_cast<uint64_t>(data[6] & 0x0F) << 56) + (static_cast<uint64_t>(data[7]) << 48);
86  uint64_t offset = 122192928000000000; // time offset in 100 ns intervals between RFC4122 Timestamp and Epoch Time
87  uint64_t ns_intervals = timestamp - offset;
88 
89  ros::Time uu1_time;
90  uu1_time.sec = static_cast<int32_t>(ns_intervals / 1e9 * 100);
91  uu1_time.nsec = static_cast<int32_t>((ns_intervals - static_cast<uint64_t>(uu1_time.sec) / (100 * 1e-9)) * 100);
92 
93  // Obtain times since epoch back from uu2
94  std::copy(uu2.begin(), uu2.end(), data.begin());
95 
96  timestamp = (static_cast<uint64_t>(data[0]) << 24) + (static_cast<uint64_t>(data[1]) << 16) +
97  (static_cast<uint64_t>(data[2]) << 8) + static_cast<uint64_t>(data[3]) +
98  (static_cast<uint64_t>(data[4]) << 40) + (static_cast<uint64_t>(data[5]) << 32) +
99  (static_cast<uint64_t>(data[6] & 0x0F) << 56) + (static_cast<uint64_t>(data[7]) << 48);
100  ns_intervals = timestamp - offset;
101 
102  ros::Time uu2_time;
103  uu2_time.sec = static_cast<int32_t>(ns_intervals / 1e9 * 100);
104  uu2_time.nsec = static_cast<int32_t>((ns_intervals - static_cast<uint64_t>(uu2_time.sec) / (100 * 1e-9)) * 100);
105 
106  // Compare
107  // Since both timestamps were in the same 100ns interval, should get same timestamp
108  EXPECT_EQ(uu1_time.sec, uu2_time.sec);
109  EXPECT_EQ(uu1_time.nsec, uu2_time.nsec);
110 
111  // While timestamps are the same, the clock_id is a randomly generated 14-bit value
112  // So, we should still expect the uuids generated to be different
113  EXPECT_NE(uu1, uu2);
114 }
115 
116 TEST(BoostUUID, timeWithinDifferentInterval)
117 {
118  ros::Time t1(1515778146, 239216020);
119  ros::Time t2(1515778146, 239216120);
120  uint64_t hw_addr = 0xAABBCCDDEEFF;
121 
122  // Generate UUIDs from times and hardware address
123  uuid uu1 = fromTime(t1, hw_addr);
124  uuid uu2 = fromTime(t2, hw_addr);
125 
126  // Obtain times since epoch back from uu1
127  std::vector<uint8_t> data(uu1.size());
128  std::copy(uu1.begin(), uu1.end(), data.begin());
129 
130  uint64_t timestamp = (static_cast<uint64_t>(data[0]) << 24) + (static_cast<uint64_t>(data[1]) << 16) +
131  (static_cast<uint64_t>(data[2]) << 8) + static_cast<uint64_t>(data[3]) +
132  (static_cast<uint64_t>(data[4]) << 40) + (static_cast<uint64_t>(data[5]) << 32) +
133  (static_cast<uint64_t>(data[6] & 0x0F) << 56) + (static_cast<uint64_t>(data[7]) << 48);
134  uint64_t offset = 122192928000000000; // time offset in 100 ns intervals between RFC4122 Timestamp and Epoch Time
135  uint64_t ns_intervals = timestamp - offset;
136 
137  ros::Time uu1_time;
138  uu1_time.sec = static_cast<int32_t>(ns_intervals / 1e9 * 100);
139  uu1_time.nsec = static_cast<int32_t>((ns_intervals - static_cast<uint64_t>(uu1_time.sec) / (100 * 1e-9)) * 100);
140 
141  // Obtain times since epoch back from uu2
142  std::copy(uu2.begin(), uu2.end(), data.begin());
143 
144  timestamp = (static_cast<uint64_t>(data[0]) << 24) + (static_cast<uint64_t>(data[1]) << 16) +
145  (static_cast<uint64_t>(data[2]) << 8) + static_cast<uint64_t>(data[3]) +
146  (static_cast<uint64_t>(data[4]) << 40) + (static_cast<uint64_t>(data[5]) << 32) +
147  (static_cast<uint64_t>(data[6] & 0x0F) << 56) + (static_cast<uint64_t>(data[7]) << 48);
148  ns_intervals = timestamp - offset;
149 
150  ros::Time uu2_time;
151  uu2_time.sec = static_cast<int32_t>(ns_intervals / 1e9 * 100);
152  uu2_time.nsec = static_cast<int32_t>((ns_intervals - static_cast<uint64_t>(uu2_time.sec) / (100 * 1e-9)) * 100);
153 
154  // Compare
155  // Since both timestamps were in different 100ns intervals, should get different timestamps (at the ns level)
156  EXPECT_EQ(uu1_time.sec, uu2_time.sec);
157  EXPECT_NE(uu1_time.nsec, uu2_time.nsec);
158 }
159 
160 TEST(BoostUUID, emptyURL)
161 {
162  std::string s;
163  uuid x = fromURL(s);
164  uuid y = fromURL(s);
165  EXPECT_EQ(x, y);
166  // MUST yield same result as Python fromURL() function:
167  EXPECT_EQ(toHexString(x), "1b4db7eb-4057-5ddf-91e0-36dec72071f5");
168 }
169 
170 TEST(BoostUUID, sameURL)
171 {
172  std::string s("http://openstreetmap.org/node/1");
173  uuid x = fromURL(s);
174  uuid y = fromURL(s);
175  EXPECT_EQ(x, y);
176  // MUST yield same result as Python fromURL() function:
177  EXPECT_EQ(toHexString(x), "ef362ac8-9659-5481-b954-88e9b741c8f9");
178 }
179 
180 TEST(BoostUUID, differentOsmNamespace)
181 {
182  uuid x = fromURL("http://openstreetmap.org/node/1");
183  uuid y = fromURL("http://openstreetmap.org/way/1");
184  EXPECT_NE(x, y);
185  // MUST yield same result as Python fromURL() function:
186  EXPECT_EQ(toHexString(y), "b3180681-b125-5e41-bd04-3c8b046175b4");
187 }
188 
189 TEST(BoostUUID, actualOsmNode)
190 {
191  uuid x = fromURL("http://openstreetmap.org/node/1");
192  uuid y = fromURL("http://openstreetmap.org/node/152370223");
193  EXPECT_NE(x, y);
194  // MUST yield same result as Python fromURL() function:
195  EXPECT_EQ(toHexString(y), "8e0b7d8a-c433-5c42-be2e-fbd97ddff9ac");
196 }
197 
198 TEST(BoostUUID, fromHexString)
199 {
200  std::string s("da7c242f-2efe-5175-9961-49cc621b80b9");
201  std::string r = toHexString(fromHexString(s));
202  EXPECT_EQ(s, r);
203 }
204 
205 TEST(BoostUUID, fromStringNoDashes)
206 {
207  std::string s("da7c242f-2efe-5175-9961-49cc621b80b9");
208  std::string s_hex("da7c242f2efe5175996149cc621b80b9");
209  std::string r = toHexString(fromHexString(s_hex));
210  EXPECT_EQ(s, r);
211 }
212 
213 TEST(BoostUUID, fromBracesString)
214 {
215  std::string s("da7c242f-2efe-5175-9961-49cc621b80b9");
216  std::string s_braces = "{" + s + "}";
217  std::string r = toHexString(fromHexString(s_braces));
218  EXPECT_EQ(s, r);
219 }
220 
221 TEST(BoostUUID, fromUrnString)
222 {
223  // This documents boost 1.46.1 behavior, but is an undefined
224  // fromHexString() input, not really a valid test case.
225  std::string s("da7c242f-2efe-5175-9961-49cc621b80b9");
226  std::string s_urn = "urn:uuid:" + s;
227  std::string r = toHexString(fromHexString(s_urn));
228  EXPECT_NE(s, r);
229 }
230 
231 TEST(BoostUUID, fromTooLongString)
232 {
233  // This documents boost 1.46.1 behavior, but is an undefined
234  // fromHexString() input, not really a valid test case.
235  std::string s("da7c242f-2efe-5175-9961-49cc621b80b9");
236  std::string s_too_long = s + "-0001";
237  std::string r = toHexString(fromHexString(s_too_long));
238  EXPECT_EQ(s, r);
239 }
240 
241 TEST(BoostUUID, fromTooShortString)
242 {
243  // This documents boost 1.46.1 behavior, but is an undefined
244  // fromHexString() input, not really a valid test case.
245  std::string s("da7c242f-2efe-5175-9961-49cc621b80");
246  try
247  {
248  uuid x = fromHexString(s);
249  FAIL(); // expected exception not thrown
250  EXPECT_NE(toHexString(x), s);
251  }
252  catch (std::runtime_error &e)
253  {
254  EXPECT_EQ(e.what(), std::string("invalid uuid string"));
255  }
256  catch (...)
257  {
258  FAIL(); // unexpected exception
259  }
260 }
261 
262 TEST(BoostUUID, fromBogusString)
263 {
264  // This documents boost 1.46.1 behavior, but is an undefined
265  // fromHexString() input, not really a valid test case.
266  std::string s("Invalid UUID string");
267  try
268  {
269  uuid x = fromHexString(s);
270  FAIL(); // expected exception not thrown
271  EXPECT_NE(toHexString(x), s);
272  }
273  catch (std::runtime_error &e)
274  {
275  EXPECT_EQ(e.what(), std::string("invalid uuid string"));
276  }
277  catch (...)
278  {
279  FAIL(); // unexpected exception
280  }
281 }
282 
283 TEST(UniqueID, nilMessage)
284 {
285  UniqueID x;
286  UniqueID y = toMsg(uuid());
287  EXPECT_EQ(x.uuid, y.uuid);
288 }
289 
290 TEST(UniqueID, randomMessage)
291 {
292  UniqueID x;
293  UniqueID y = toMsg(fromRandom());
294  EXPECT_NE(x.uuid, y.uuid);
295 }
296 
297 TEST(UniqueID, equivalentMessages)
298 {
299  std::string s("da7c242f-2efe-5175-9961-49cc621b80b9");
300  UniqueID x = toMsg(fromHexString(s));
301  UniqueID y = toMsg(fromHexString(s));
302  EXPECT_EQ(x.uuid, y.uuid);
303  EXPECT_EQ(s, toHexString(y));
304 }
305 
306 TEST(UniqueID, toAndFromMessage)
307 {
308  std::string s("da7c242f-2efe-5175-9961-49cc621b80b9");
309  uuid x = uuid(fromHexString(s));
310  uuid y = fromMsg(toMsg(x));
311  EXPECT_EQ(x, y);
312 }
313 
314 TEST(UniqueID, messageToString)
315 {
316  std::string s("da7c242f-2efe-5175-9961-49cc621b80b9");
317  UniqueID x = toMsg(fromHexString(s));
318  std::string y = toHexString(x);
319  EXPECT_EQ(s, y);
320 }
321 
322 // Run all the tests that were declared with TEST()
323 int main(int argc, char **argv)
324 {
325  testing::InitGoogleTest(&argc, argv);
326  return RUN_ALL_TESTS();
327 }
static boost::uuids::uuid fromRandom(void)
Generate a random UUID object.
Definition: unique_id.h:100
uuid_msgs::UniqueID UniqueID
static boost::uuids::uuid fromMsg(uuid_msgs::UniqueID const &msg)
Create UUID object from UniqueID message.
Definition: unique_id.h:85
C++ namespace for unique_id helper functions.
TEST(BoostUUID, fromRandom)
XmlRpcServer s
int main(int argc, char **argv)
static boost::uuids::uuid fromTime(ros::Time timestamp, uint64_t hw_addr)
Generate a Time Based UUID object. Users are recommended to seed the random number generator using sr...
Definition: unique_id.h:167
uuid_msgs::UniqueID UniqueID
boost::uuids::uuid uuid
static std::string toHexString(boost::uuids::uuid const &uu)
Get the canonical string representation for a boost UUID.
Definition: unique_id.h:192
boost::uuids::uuid uuid
static boost::uuids::uuid fromURL(std::string const &url)
Generate UUID from Uniform Resource Identifier.
Definition: unique_id.h:151
static uuid_msgs::UniqueID toMsg(boost::uuids::uuid const &uu)
Create a UniqueID message from a UUID object.
Definition: unique_id.h:177
static boost::uuids::uuid fromHexString(std::string const &str)
Generate UUID from canonical hex string.
Definition: unique_id.h:125
Helper functions for universally unique identifiers and messages.


unique_id
Author(s): Jack O'Quin
autogenerated on Mon Mar 6 2023 03:18:07