blob: 01bd884c674e6b6701c691a95a80e741762c36d0 [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
53
Alexander Afanasyevc2344292014-03-02 00:08:00 +000054BOOST_AUTO_TEST_CASE(Basic)
55{
56 Name name("/hello/world");
57
58 BOOST_CHECK_NO_THROW(name.at(0));
59 BOOST_CHECK_NO_THROW(name.at(1));
60 BOOST_CHECK_NO_THROW(name.at(-1));
61 BOOST_CHECK_NO_THROW(name.at(-2));
62
63 BOOST_CHECK_THROW(name.at(2), Name::Error);
64 BOOST_CHECK_THROW(name.at(-3), Name::Error);
65}
66
67BOOST_AUTO_TEST_CASE(Encode)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080068{
69 Name name("/local/ndn/prefix");
70
71 const Block &wire = name.wireEncode();
72
73 // for (Buffer::const_iterator i = wire.begin();
74 // i != wire.end();
75 // ++i)
76 // {
77 // std::ios::fmtflags saveFlags = std::cout.flags(std::ios::hex);
78
79 // if (i != wire.begin())
80 // std::cout << ", ";
81 // std::cout << "0x" << static_cast<uint32_t>(*i);
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070082
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080083 // std::cout.flags(saveFlags);
84 // }
85 // std::cout << std::endl;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -070086
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -080087 BOOST_CHECK_EQUAL_COLLECTIONS(TestName, TestName+sizeof(TestName),
88 wire.begin(), wire.end());
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080089}
90
91
Alexander Afanasyevc2344292014-03-02 00:08:00 +000092BOOST_AUTO_TEST_CASE(Decode)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080093{
94 Block block(TestName, sizeof(TestName));
95
96 Name name(block);
97
98 BOOST_CHECK_EQUAL(name.toUri(), "/local/ndn/prefix");
99}
100
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000101BOOST_AUTO_TEST_CASE(AppendsAndMultiEncode)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800102{
103 Name name("/local");
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700104
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800105 BOOST_CHECK_EQUAL_COLLECTIONS(name.wireEncode().begin(), name.wireEncode().end(),
Alexander Afanasyev4b456282014-02-13 00:34:34 -0800106 Name1, Name1 + sizeof(Name1));
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800107
108 name.append("ndn");
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700109
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800110 BOOST_CHECK_EQUAL_COLLECTIONS(name.wireEncode().begin(), name.wireEncode().end(),
Alexander Afanasyev4b456282014-02-13 00:34:34 -0800111 Name2, Name2 + sizeof(Name2));
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800112
113 name.append("prefix");
114 BOOST_CHECK_EQUAL_COLLECTIONS(name.wireEncode().begin(), name.wireEncode().end(),
115 TestName, TestName+sizeof(TestName));
116}
117
Steve DiBenedettoc145d492014-03-11 16:35:45 -0600118BOOST_AUTO_TEST_CASE(AppendNumber)
119{
120 Name name;
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700121 for (uint32_t i = 0; i < 10; i++)
Steve DiBenedettoc145d492014-03-11 16:35:45 -0600122 {
123 name.appendNumber(i);
124 }
125
126 BOOST_CHECK_EQUAL(name.size(), 10);
127
Alexander Afanasyevb1db7c62014-04-03 14:57:25 -0700128 for (uint32_t i = 0; i < 10; i++)
Steve DiBenedettoc145d492014-03-11 16:35:45 -0600129 {
130 BOOST_CHECK_EQUAL(name[i].toNumber(), i);
131 }
132}
133
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700134class Numeric
135{
136public:
137 typedef std::list<boost::tuple<function<name::Component(uint64_t)>,
138 function<uint64_t(const name::Component&)>,
139 function<Name&(Name&, uint64_t)>,
140 Name/*expected*/,
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700141 uint64_t/*value*/,
142 function<bool(const name::Component&)> > > Dataset;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700143
144 Numeric()
145 {
146 dataset.push_back(boost::make_tuple(bind(&name::Component::fromNumberWithMarker,
147 0xAA, _1),
148 bind(&name::Component::toNumberWithMarker, _1, 0xAA),
149 bind(&Name::appendNumberWithMarker, _1, 0xAA, _2),
150 Name("/%AA%03%E8"),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700151 1000,
152 bind(&name::Component::isNumberWithMarker, _1, 0xAA)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700153 dataset.push_back(boost::make_tuple(&name::Component::fromSegment,
154 bind(&name::Component::toSegment, _1),
155 bind(&Name::appendSegment, _1, _2),
156 Name("/%00%27%10"),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700157 10000,
158 bind(&name::Component::isSegment, _1)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700159 dataset.push_back(boost::make_tuple(&name::Component::fromSegmentOffset,
160 bind(&name::Component::toSegmentOffset, _1),
161 bind(&Name::appendSegmentOffset, _1, _2),
162 Name("/%FB%00%01%86%A0"),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700163 100000,
164 bind(&name::Component::isSegmentOffset, _1)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700165 dataset.push_back(boost::make_tuple(&name::Component::fromVersion,
166 bind(&name::Component::toVersion, _1),
Davide Pesaventodfe9c6b2014-08-25 21:17:10 +0200167 bind(static_cast<Name&(Name::*)(uint64_t)>(
168 &Name::appendVersion), _1, _2),
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700169 Name("/%FD%00%0FB%40"),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700170 1000000,
171 bind(&name::Component::isVersion, _1)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700172 dataset.push_back(boost::make_tuple(&name::Component::fromSequenceNumber,
173 bind(&name::Component::toSequenceNumber, _1),
174 bind(&Name::appendSequenceNumber, _1, _2),
175 Name("/%FE%00%98%96%80"),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700176 10000000,
177 bind(&name::Component::isSequenceNumber, _1)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700178 }
179
180 Dataset dataset;
181};
182
183class Timestamp
184{
185public:
186 typedef std::list<boost::tuple<function<name::Component(const time::system_clock::TimePoint&)>,
187 function<time::system_clock::TimePoint(const name::Component&)>,
188 function<Name&(Name&, const time::system_clock::TimePoint&)>,
189 Name/*expected*/,
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700190 time::system_clock::TimePoint/*value*/,
191 function<bool(const name::Component&)> > > Dataset;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700192 Timestamp()
193 {
194 dataset.push_back(boost::make_tuple(&name::Component::fromTimestamp,
Alexander Afanasyev6f9ec932014-10-31 10:34:00 -0700195 ndn::bind(&name::Component::toTimestamp, _1),
196 ndn::bind(&Name::appendTimestamp, _1, _2),
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700197 Name("/%FC%00%04%7BE%E3%1B%00%00"),
Davide Pesaventodfe9c6b2014-08-25 21:17:10 +0200198 time::getUnixEpoch() + time::days(14600/*40 years*/),
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700199 bind(&name::Component::isTimestamp, _1)));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700200 }
201
202 Dataset dataset;
203};
204
205typedef boost::mpl::vector<Numeric, Timestamp> ConventionsDatasets;
206
207BOOST_FIXTURE_TEST_CASE_TEMPLATE(NamingConventions, T, ConventionsDatasets, T)
208{
209 // // These octets are obtained by the snippet below.
210 // // This check is intended to detect unexpected encoding change in the future.
211 // for (typename T::Dataset::const_iterator it = this->dataset.begin();
212 // it != this->dataset.end(); ++it) {
213 // Name name;
214 // name.append(it->template get<0>()(it->template get<4>()));
215 // std::cout << name << std::endl;
216 // }
217
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700218 name::Component invalidComponent1;
219 name::Component invalidComponent2("1234567890");
220
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700221 for (typename T::Dataset::const_iterator it = this->dataset.begin();
222 it != this->dataset.end(); ++it) {
223 const Name& expected = it->template get<3>();
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700224 BOOST_TEST_MESSAGE("Check " << expected[0].toUri());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700225
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700226 BOOST_CHECK_EQUAL(expected[0].isGeneric(), true);
227
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700228 name::Component actualComponent = it->template get<0>()(it->template get<4>());
229 BOOST_CHECK_EQUAL(actualComponent, expected[0]);
230
231 Name actualName;
232 it->template get<2>()(actualName, it->template get<4>());
233 BOOST_CHECK_EQUAL(actualName, expected);
234
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700235 BOOST_CHECK_EQUAL(it->template get<5>()(expected[0]), true);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700236 BOOST_REQUIRE_NO_THROW(it->template get<1>()(expected[0]));
237 BOOST_CHECK_EQUAL(it->template get<1>()(expected[0]), it->template get<4>());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700238
239 BOOST_CHECK_EQUAL(it->template get<5>()(invalidComponent1), false);
240 BOOST_CHECK_EQUAL(it->template get<5>()(invalidComponent2), false);
241
242 BOOST_REQUIRE_THROW(it->template get<1>()(invalidComponent1), name::Component::Error);
243 BOOST_REQUIRE_THROW(it->template get<1>()(invalidComponent2), name::Component::Error);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700244 }
245}
246
Shuo Chen5aa8c742014-06-22 15:00:02 +0800247BOOST_AUTO_TEST_CASE(GetSuccessor)
248{
249 BOOST_CHECK_EQUAL(Name("ndn:/%00%01/%01%02").getSuccessor(), Name("ndn:/%00%01/%01%03"));
250 BOOST_CHECK_EQUAL(Name("ndn:/%00%01/%01%FF").getSuccessor(), Name("ndn:/%00%01/%02%00"));
251 BOOST_CHECK_EQUAL(Name("ndn:/%00%01/%FF%FF").getSuccessor(), Name("ndn:/%00%01/%00%00%00"));
252 BOOST_CHECK_EQUAL(Name().getSuccessor(), Name("ndn:/%00"));
253}
254
Junxiao Shi937e4612014-10-22 15:39:07 -0700255BOOST_AUTO_TEST_CASE(Markers)
256{
257 Name name;
258 uint64_t number;
259
260 BOOST_REQUIRE_NO_THROW(number = name.appendSegment(30923).at(-1).toSegment());
261 BOOST_CHECK_EQUAL(number, 30923);
262
263 BOOST_REQUIRE_NO_THROW(number = name.appendSegmentOffset(589).at(-1).toSegmentOffset());
264 BOOST_CHECK_EQUAL(number, 589);
265
266 BOOST_REQUIRE_NO_THROW(number = name.appendVersion().at(-1).toVersion());
267
268 BOOST_REQUIRE_NO_THROW(number = name.appendVersion(25912).at(-1).toVersion());
269 BOOST_CHECK_EQUAL(number, 25912);
270
271 const time::system_clock::TimePoint tp = time::system_clock::now();
272 time::system_clock::TimePoint tp2;
273 BOOST_REQUIRE_NO_THROW(tp2 = name.appendTimestamp(tp).at(-1).toTimestamp());
274 BOOST_CHECK_LE(std::abs(time::duration_cast<time::microseconds>(tp2 - tp).count()), 1);
275
276 BOOST_REQUIRE_NO_THROW(number = name.appendSequenceNumber(11676).at(-1).toSequenceNumber());
277 BOOST_CHECK_EQUAL(number, 11676);
278}
279
Yingdi Yu90e23582014-11-06 14:21:04 -0800280BOOST_AUTO_TEST_CASE(UnorderedMap)
281{
282 std::unordered_map<Name, int> map;
283 Name name1("/1");
284 Name name2("/2");
285 Name name3("/3");
286 map[name1] = 1;
287 map[name2] = 2;
288 map[name3] = 3;
289
290 BOOST_CHECK_EQUAL(map[name1], 1);
291 BOOST_CHECK_EQUAL(map[name2], 2);
292 BOOST_CHECK_EQUAL(map[name3], 3);
293}
294
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700295BOOST_AUTO_TEST_CASE(ImplictSha256Digest)
296{
297 Name n;
298
299 static const uint8_t DIGEST[] = { 0x28, 0xba, 0xd4, 0xb5, 0x27, 0x5b, 0xd3, 0x92,
300 0xdb, 0xb6, 0x70, 0xc7, 0x5c, 0xf0, 0xb6, 0x6f,
301 0x13, 0xf7, 0x94, 0x2b, 0x21, 0xe8, 0x0f, 0x55,
302 0xc0, 0xe8, 0x6b, 0x37, 0x47, 0x53, 0xa5, 0x48 };
303
304 BOOST_REQUIRE_NO_THROW(n.appendImplicitSha256Digest(DIGEST, 32));
305 BOOST_REQUIRE_NO_THROW(n.appendImplicitSha256Digest(make_shared<Buffer>(DIGEST, 32)));
306 BOOST_CHECK_EQUAL(n.get(0), n.get(1));
307
308 BOOST_REQUIRE_THROW(n.appendImplicitSha256Digest(DIGEST, 34), name::Component::Error);
309 BOOST_REQUIRE_THROW(n.appendImplicitSha256Digest(DIGEST, 30), name::Component::Error);
310
311 n.append(DIGEST, 32);
312 BOOST_CHECK_LT(n.get(0), n.get(2));
313 BOOST_CHECK_EQUAL_COLLECTIONS(n.get(0).value_begin(), n.get(0).value_end(),
314 n.get(2).value_begin(), n.get(2).value_end());
315
316 n.append(DIGEST + 1, 32);
317 BOOST_CHECK_LT(n.get(0), n.get(3));
318
319 n.append(DIGEST + 2, 32);
320 BOOST_CHECK_LT(n.get(0), n.get(4));
321
322 BOOST_CHECK_EQUAL(n.get(0).toUri(), "sha256digest="
323 "28bad4b5275bd392dbb670c75cf0b66f13f7942b21e80f55c0e86b374753a548");
324
325 BOOST_CHECK_EQUAL(n.get(0).isImplicitSha256Digest(), true);
326 BOOST_CHECK_EQUAL(n.get(2).isImplicitSha256Digest(), false);
327
328 BOOST_CHECK_THROW(Name("/hello/sha256digest=hmm"), name::Component::Error);
329
330 Name n2;
331 // check canonical URI encoding (lower case)
332 BOOST_CHECK_NO_THROW(n2 = Name("/hello/sha256digest="
333 "28bad4b5275bd392dbb670c75cf0b66f13f7942b21e80f55c0e86b374753a548"));
334 BOOST_CHECK_EQUAL(n.get(0), n2.get(1));
335
336 // will accept hex value in upper case too
337 BOOST_CHECK_NO_THROW(n2 = Name("/hello/sha256digest="
338 "28BAD4B5275BD392DBB670C75CF0B66F13F7942B21E80F55C0E86B374753A548"));
339 BOOST_CHECK_EQUAL(n.get(0), n2.get(1));
340
341 // this is not valid sha256digest component, will be treated as generic component
342 BOOST_CHECK_NO_THROW(n2 = Name("/hello/SHA256DIGEST="
343 "28BAD4B5275BD392DBB670C75CF0B66F13F7942B21E80F55C0E86B374753A548"));
344 BOOST_CHECK_NE(n.get(0), n2.get(1));
345}
346
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800347BOOST_AUTO_TEST_SUITE_END()
348
349} // namespace ndn