blob: 8c86d79a7650063b8c55794166a9d52bb2c2b6f7 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -08002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080020 */
21
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080022#include "name.hpp"
23
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070024#include "boost-test.hpp"
Alexander Afanasyev15f67312014-07-22 15:11:09 -070025#include <boost/tuple/tuple.hpp>
26#include <boost/mpl/vector.hpp>
Yingdi Yu90e23582014-11-06 14:21:04 -080027#include <unordered_map>
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070028
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080029namespace ndn {
30
31BOOST_AUTO_TEST_SUITE(TestName)
32
33static const uint8_t TestName[] = {
Alexander Afanasyev4b456282014-02-13 00:34:34 -080034 0x7, 0x14, // Name
35 0x8, 0x5, // NameComponent
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080036 0x6c, 0x6f, 0x63, 0x61, 0x6c,
Alexander Afanasyev4b456282014-02-13 00:34:34 -080037 0x8, 0x3, // NameComponent
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080038 0x6e, 0x64, 0x6e,
Alexander Afanasyev4b456282014-02-13 00:34:34 -080039 0x8, 0x6, // NameComponent
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080040 0x70, 0x72, 0x65, 0x66, 0x69, 0x78
41};
42
Alexander Afanasyev4b456282014-02-13 00:34:34 -080043const uint8_t Name1[] = {0x7, 0x7, // Name
44 0x8, 0x5, // NameComponent
45 0x6c, 0x6f, 0x63, 0x61, 0x6c};
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070046
Alexander Afanasyev4b456282014-02-13 00:34:34 -080047const uint8_t Name2[] = {0x7, 0xc, // Name
48 0x8, 0x5, // NameComponent
49 0x6c, 0x6f, 0x63, 0x61, 0x6c,
50 0x8, 0x3, // NameComponent
51 0x6e, 0x64, 0x6e};
52
Qiuhan Ding2c3cbe42014-11-25 18:10:23 -080053static const uint8_t TestNameComponent[] = {
54 0x8, 0x3, // NameComponent
55 0x6e, 0x64, 0x6e};
56
57static const uint8_t TestDigestComponent[] = {
58 0x1, 0x20, // ImplicitSha256DigestComponent
59 0x28, 0xba, 0xd4, 0xb5, 0x27, 0x5b, 0xd3, 0x92,
60 0xdb, 0xb6, 0x70, 0xc7, 0x5c, 0xf0, 0xb6, 0x6f,
61 0x13, 0xf7, 0x94, 0x2b, 0x21, 0xe8, 0x0f, 0x55,
62 0xc0, 0xe8, 0x6b, 0x37, 0x47, 0x53, 0xa5, 0x48 };
63
64const uint8_t Component1[] = {0x7, 0x3, // Error in Type
65 0x6e, 0x64, 0x6e};
66
Alexander Afanasyev4b456282014-02-13 00:34:34 -080067
Alexander Afanasyevc2344292014-03-02 00:08:00 +000068BOOST_AUTO_TEST_CASE(Basic)
69{
70 Name name("/hello/world");
71
72 BOOST_CHECK_NO_THROW(name.at(0));
73 BOOST_CHECK_NO_THROW(name.at(1));
74 BOOST_CHECK_NO_THROW(name.at(-1));
75 BOOST_CHECK_NO_THROW(name.at(-2));
76
77 BOOST_CHECK_THROW(name.at(2), Name::Error);
78 BOOST_CHECK_THROW(name.at(-3), Name::Error);
79}
80
81BOOST_AUTO_TEST_CASE(Encode)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080082{
83 Name name("/local/ndn/prefix");
84
85 const Block &wire = name.wireEncode();
86
87 // for (Buffer::const_iterator i = wire.begin();
88 // i != wire.end();
89 // ++i)
90 // {
91 // std::ios::fmtflags saveFlags = std::cout.flags(std::ios::hex);
92
93 // if (i != wire.begin())
94 // std::cout << ", ";
95 // std::cout << "0x" << static_cast<uint32_t>(*i);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070096
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080097 // std::cout.flags(saveFlags);
98 // }
99 // std::cout << std::endl;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700100
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800101 BOOST_CHECK_EQUAL_COLLECTIONS(TestName, TestName+sizeof(TestName),
102 wire.begin(), wire.end());
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800103}
104
105
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000106BOOST_AUTO_TEST_CASE(Decode)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800107{
108 Block block(TestName, sizeof(TestName));
109
110 Name name(block);
111
112 BOOST_CHECK_EQUAL(name.toUri(), "/local/ndn/prefix");
113}
114
Qiuhan Ding2c3cbe42014-11-25 18:10:23 -0800115BOOST_AUTO_TEST_CASE(DecodeComponent)
116{
117 Block componentBlock(TestNameComponent, sizeof(TestNameComponent));
118 name::Component nameComponent;
119 BOOST_REQUIRE_NO_THROW(nameComponent.wireDecode(componentBlock));
120 BOOST_CHECK_EQUAL(nameComponent.toUri(), "ndn");
121
122 Block digestComponentBlock(TestDigestComponent, sizeof(TestDigestComponent));
123 name::Component digestComponent;
124 BOOST_REQUIRE_NO_THROW(digestComponent.wireDecode(digestComponentBlock));
125
126 Block errorBlock(Component1, sizeof(Component1));
127 name::Component errorComponent;
128 BOOST_REQUIRE_THROW(errorComponent.wireDecode(errorBlock), name::Component::Error);
129}
130
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000131BOOST_AUTO_TEST_CASE(AppendsAndMultiEncode)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800132{
133 Name name("/local");
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700134
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800135 BOOST_CHECK_EQUAL_COLLECTIONS(name.wireEncode().begin(), name.wireEncode().end(),
Alexander Afanasyev4b456282014-02-13 00:34:34 -0800136 Name1, Name1 + sizeof(Name1));
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800137
138 name.append("ndn");
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700139
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800140 BOOST_CHECK_EQUAL_COLLECTIONS(name.wireEncode().begin(), name.wireEncode().end(),
Alexander Afanasyev4b456282014-02-13 00:34:34 -0800141 Name2, Name2 + sizeof(Name2));
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800142
143 name.append("prefix");
144 BOOST_CHECK_EQUAL_COLLECTIONS(name.wireEncode().begin(), name.wireEncode().end(),
145 TestName, TestName+sizeof(TestName));
146}
147
Steve DiBenedettoc145d492014-03-11 16:35:45 -0600148BOOST_AUTO_TEST_CASE(AppendNumber)
149{
150 Name name;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700151 for (uint32_t i = 0; i < 10; i++)
Steve DiBenedettoc145d492014-03-11 16:35:45 -0600152 {
153 name.appendNumber(i);
154 }
155
156 BOOST_CHECK_EQUAL(name.size(), 10);
157
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700158 for (uint32_t i = 0; i < 10; i++)
Steve DiBenedettoc145d492014-03-11 16:35:45 -0600159 {
160 BOOST_CHECK_EQUAL(name[i].toNumber(), i);
161 }
162}
163
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700164class Numeric
165{
166public:
167 typedef std::list<boost::tuple<function<name::Component(uint64_t)>,
168 function<uint64_t(const name::Component&)>,
169 function<Name&(Name&, uint64_t)>,
170 Name/*expected*/,
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700171 uint64_t/*value*/,
172 function<bool(const name::Component&)> > > Dataset;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700173
174 Numeric()
175 {
176 dataset.push_back(boost::make_tuple(bind(&name::Component::fromNumberWithMarker,
177 0xAA, _1),
178 bind(&name::Component::toNumberWithMarker, _1, 0xAA),
179 bind(&Name::appendNumberWithMarker, _1, 0xAA, _2),
180 Name("/%AA%03%E8"),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700181 1000,
182 bind(&name::Component::isNumberWithMarker, _1, 0xAA)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700183 dataset.push_back(boost::make_tuple(&name::Component::fromSegment,
184 bind(&name::Component::toSegment, _1),
185 bind(&Name::appendSegment, _1, _2),
186 Name("/%00%27%10"),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700187 10000,
188 bind(&name::Component::isSegment, _1)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700189 dataset.push_back(boost::make_tuple(&name::Component::fromSegmentOffset,
190 bind(&name::Component::toSegmentOffset, _1),
191 bind(&Name::appendSegmentOffset, _1, _2),
192 Name("/%FB%00%01%86%A0"),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700193 100000,
194 bind(&name::Component::isSegmentOffset, _1)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700195 dataset.push_back(boost::make_tuple(&name::Component::fromVersion,
196 bind(&name::Component::toVersion, _1),
Davide Pesaventodfe9c6b2014-08-25 21:17:10 +0200197 bind(static_cast<Name&(Name::*)(uint64_t)>(
198 &Name::appendVersion), _1, _2),
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700199 Name("/%FD%00%0FB%40"),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700200 1000000,
201 bind(&name::Component::isVersion, _1)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700202 dataset.push_back(boost::make_tuple(&name::Component::fromSequenceNumber,
203 bind(&name::Component::toSequenceNumber, _1),
204 bind(&Name::appendSequenceNumber, _1, _2),
205 Name("/%FE%00%98%96%80"),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700206 10000000,
207 bind(&name::Component::isSequenceNumber, _1)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700208 }
209
210 Dataset dataset;
211};
212
213class Timestamp
214{
215public:
216 typedef std::list<boost::tuple<function<name::Component(const time::system_clock::TimePoint&)>,
217 function<time::system_clock::TimePoint(const name::Component&)>,
218 function<Name&(Name&, const time::system_clock::TimePoint&)>,
219 Name/*expected*/,
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700220 time::system_clock::TimePoint/*value*/,
221 function<bool(const name::Component&)> > > Dataset;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700222 Timestamp()
223 {
224 dataset.push_back(boost::make_tuple(&name::Component::fromTimestamp,
Alexander Afanasyev6f9ec932014-10-31 10:34:00 -0700225 ndn::bind(&name::Component::toTimestamp, _1),
226 ndn::bind(&Name::appendTimestamp, _1, _2),
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700227 Name("/%FC%00%04%7BE%E3%1B%00%00"),
Davide Pesaventodfe9c6b2014-08-25 21:17:10 +0200228 time::getUnixEpoch() + time::days(14600/*40 years*/),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700229 bind(&name::Component::isTimestamp, _1)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700230 }
231
232 Dataset dataset;
233};
234
235typedef boost::mpl::vector<Numeric, Timestamp> ConventionsDatasets;
236
237BOOST_FIXTURE_TEST_CASE_TEMPLATE(NamingConventions, T, ConventionsDatasets, T)
238{
239 // // These octets are obtained by the snippet below.
240 // // This check is intended to detect unexpected encoding change in the future.
241 // for (typename T::Dataset::const_iterator it = this->dataset.begin();
242 // it != this->dataset.end(); ++it) {
243 // Name name;
244 // name.append(it->template get<0>()(it->template get<4>()));
245 // std::cout << name << std::endl;
246 // }
247
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700248 name::Component invalidComponent1;
249 name::Component invalidComponent2("1234567890");
250
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700251 for (typename T::Dataset::const_iterator it = this->dataset.begin();
252 it != this->dataset.end(); ++it) {
253 const Name& expected = it->template get<3>();
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700254 BOOST_TEST_MESSAGE("Check " << expected[0].toUri());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700255
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700256 BOOST_CHECK_EQUAL(expected[0].isGeneric(), true);
257
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700258 name::Component actualComponent = it->template get<0>()(it->template get<4>());
259 BOOST_CHECK_EQUAL(actualComponent, expected[0]);
260
261 Name actualName;
262 it->template get<2>()(actualName, it->template get<4>());
263 BOOST_CHECK_EQUAL(actualName, expected);
264
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700265 BOOST_CHECK_EQUAL(it->template get<5>()(expected[0]), true);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700266 BOOST_REQUIRE_NO_THROW(it->template get<1>()(expected[0]));
267 BOOST_CHECK_EQUAL(it->template get<1>()(expected[0]), it->template get<4>());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700268
269 BOOST_CHECK_EQUAL(it->template get<5>()(invalidComponent1), false);
270 BOOST_CHECK_EQUAL(it->template get<5>()(invalidComponent2), false);
271
272 BOOST_REQUIRE_THROW(it->template get<1>()(invalidComponent1), name::Component::Error);
273 BOOST_REQUIRE_THROW(it->template get<1>()(invalidComponent2), name::Component::Error);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700274 }
275}
276
Shuo Chen5aa8c742014-06-22 15:00:02 +0800277BOOST_AUTO_TEST_CASE(GetSuccessor)
278{
279 BOOST_CHECK_EQUAL(Name("ndn:/%00%01/%01%02").getSuccessor(), Name("ndn:/%00%01/%01%03"));
280 BOOST_CHECK_EQUAL(Name("ndn:/%00%01/%01%FF").getSuccessor(), Name("ndn:/%00%01/%02%00"));
281 BOOST_CHECK_EQUAL(Name("ndn:/%00%01/%FF%FF").getSuccessor(), Name("ndn:/%00%01/%00%00%00"));
282 BOOST_CHECK_EQUAL(Name().getSuccessor(), Name("ndn:/%00"));
283}
284
Junxiao Shi937e4612014-10-22 15:39:07 -0700285BOOST_AUTO_TEST_CASE(Markers)
286{
287 Name name;
288 uint64_t number;
289
290 BOOST_REQUIRE_NO_THROW(number = name.appendSegment(30923).at(-1).toSegment());
291 BOOST_CHECK_EQUAL(number, 30923);
292
293 BOOST_REQUIRE_NO_THROW(number = name.appendSegmentOffset(589).at(-1).toSegmentOffset());
294 BOOST_CHECK_EQUAL(number, 589);
295
296 BOOST_REQUIRE_NO_THROW(number = name.appendVersion().at(-1).toVersion());
297
298 BOOST_REQUIRE_NO_THROW(number = name.appendVersion(25912).at(-1).toVersion());
299 BOOST_CHECK_EQUAL(number, 25912);
300
301 const time::system_clock::TimePoint tp = time::system_clock::now();
302 time::system_clock::TimePoint tp2;
303 BOOST_REQUIRE_NO_THROW(tp2 = name.appendTimestamp(tp).at(-1).toTimestamp());
304 BOOST_CHECK_LE(std::abs(time::duration_cast<time::microseconds>(tp2 - tp).count()), 1);
305
306 BOOST_REQUIRE_NO_THROW(number = name.appendSequenceNumber(11676).at(-1).toSequenceNumber());
307 BOOST_CHECK_EQUAL(number, 11676);
308}
309
Yingdi Yu90e23582014-11-06 14:21:04 -0800310BOOST_AUTO_TEST_CASE(UnorderedMap)
311{
312 std::unordered_map<Name, int> map;
313 Name name1("/1");
314 Name name2("/2");
315 Name name3("/3");
316 map[name1] = 1;
317 map[name2] = 2;
318 map[name3] = 3;
319
320 BOOST_CHECK_EQUAL(map[name1], 1);
321 BOOST_CHECK_EQUAL(map[name2], 2);
322 BOOST_CHECK_EQUAL(map[name3], 3);
323}
324
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700325BOOST_AUTO_TEST_CASE(ImplictSha256Digest)
326{
327 Name n;
328
329 static const uint8_t DIGEST[] = { 0x28, 0xba, 0xd4, 0xb5, 0x27, 0x5b, 0xd3, 0x92,
330 0xdb, 0xb6, 0x70, 0xc7, 0x5c, 0xf0, 0xb6, 0x6f,
331 0x13, 0xf7, 0x94, 0x2b, 0x21, 0xe8, 0x0f, 0x55,
332 0xc0, 0xe8, 0x6b, 0x37, 0x47, 0x53, 0xa5, 0x48 };
333
334 BOOST_REQUIRE_NO_THROW(n.appendImplicitSha256Digest(DIGEST, 32));
335 BOOST_REQUIRE_NO_THROW(n.appendImplicitSha256Digest(make_shared<Buffer>(DIGEST, 32)));
336 BOOST_CHECK_EQUAL(n.get(0), n.get(1));
337
338 BOOST_REQUIRE_THROW(n.appendImplicitSha256Digest(DIGEST, 34), name::Component::Error);
339 BOOST_REQUIRE_THROW(n.appendImplicitSha256Digest(DIGEST, 30), name::Component::Error);
340
341 n.append(DIGEST, 32);
342 BOOST_CHECK_LT(n.get(0), n.get(2));
343 BOOST_CHECK_EQUAL_COLLECTIONS(n.get(0).value_begin(), n.get(0).value_end(),
344 n.get(2).value_begin(), n.get(2).value_end());
345
346 n.append(DIGEST + 1, 32);
347 BOOST_CHECK_LT(n.get(0), n.get(3));
348
349 n.append(DIGEST + 2, 32);
350 BOOST_CHECK_LT(n.get(0), n.get(4));
351
352 BOOST_CHECK_EQUAL(n.get(0).toUri(), "sha256digest="
353 "28bad4b5275bd392dbb670c75cf0b66f13f7942b21e80f55c0e86b374753a548");
354
355 BOOST_CHECK_EQUAL(n.get(0).isImplicitSha256Digest(), true);
356 BOOST_CHECK_EQUAL(n.get(2).isImplicitSha256Digest(), false);
357
358 BOOST_CHECK_THROW(Name("/hello/sha256digest=hmm"), name::Component::Error);
359
360 Name n2;
361 // check canonical URI encoding (lower case)
362 BOOST_CHECK_NO_THROW(n2 = Name("/hello/sha256digest="
363 "28bad4b5275bd392dbb670c75cf0b66f13f7942b21e80f55c0e86b374753a548"));
364 BOOST_CHECK_EQUAL(n.get(0), n2.get(1));
365
366 // will accept hex value in upper case too
367 BOOST_CHECK_NO_THROW(n2 = Name("/hello/sha256digest="
368 "28BAD4B5275BD392DBB670C75CF0B66F13F7942B21E80F55C0E86B374753A548"));
369 BOOST_CHECK_EQUAL(n.get(0), n2.get(1));
370
371 // this is not valid sha256digest component, will be treated as generic component
372 BOOST_CHECK_NO_THROW(n2 = Name("/hello/SHA256DIGEST="
373 "28BAD4B5275BD392DBB670C75CF0B66F13F7942B21E80F55C0E86B374753A548"));
374 BOOST_CHECK_NE(n.get(0), n2.get(1));
375}
376
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800377BOOST_AUTO_TEST_SUITE_END()
378
379} // namespace ndn