blob: 535e8bde4f025f480b8e84f957eb67df9e4435c1 [file] [log] [blame]
Yanbiao Li8ee37ed2015-05-19 12:44:04 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shic542f632017-07-18 14:20:32 +00002/*
Alexander Afanasyev70244f42017-01-04 12:47:12 -08003 * Copyright (c) 2013-2017 Regents of the University of California.
Yanbiao Li8ee37ed2015-05-19 12:44:04 -07004 *
Alexander Afanasyev80b68e12015-09-17 17:01:04 -07005 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Yanbiao Li8ee37ed2015-05-19 12:44:04 -07006 *
Alexander Afanasyev80b68e12015-09-17 17:01:04 -07007 * 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.
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070010 *
Alexander Afanasyev80b68e12015-09-17 17:01:04 -070011 * 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.
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070014 *
Alexander Afanasyev80b68e12015-09-17 17:01:04 -070015 * 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.
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070020 */
21
22#include "mgmt/dispatcher.hpp"
Junxiao Shi7357ef22016-09-07 02:39:37 +000023#include "mgmt/nfd/control-parameters.hpp"
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070024#include "util/dummy-client-face.hpp"
25
26#include "boost-test.hpp"
Junxiao Shi2bea5c42017-08-14 20:10:32 +000027#include "make-interest-data.hpp"
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -070028#include "../identity-management-time-fixture.hpp"
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070029
30namespace ndn {
31namespace mgmt {
32namespace tests {
33
34using namespace ndn::tests;
35
Alexander Afanasyev80782e02017-01-04 13:16:54 -080036class DispatcherFixture : public IdentityManagementTimeFixture
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070037{
38public:
39 DispatcherFixture()
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -070040 : face(io, m_keyChain, {true, true})
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080041 , dispatcher(face, m_keyChain, security::SigningInfo())
Yanbiao Li4b4f7542016-03-11 02:04:43 +080042 , storage(dispatcher.m_storage)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070043 {
44 }
45
46public:
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080047 util::DummyClientFace face;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070048 mgmt::Dispatcher dispatcher;
Junxiao Shic542f632017-07-18 14:20:32 +000049 InMemoryStorageFifo& storage;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070050};
51
52class VoidParameters : public mgmt::ControlParameters
53{
54public:
55 explicit
56 VoidParameters(const Block& wire)
57 {
58 wireDecode(wire);
59 }
60
Junxiao Shid97c9532017-04-27 16:17:04 +000061 Block
Davide Pesaventoaa82eb62016-04-22 19:08:40 +020062 wireEncode() const final
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070063 {
64 return Block(128);
65 }
66
Junxiao Shid97c9532017-04-27 16:17:04 +000067 void
Davide Pesaventoaa82eb62016-04-22 19:08:40 +020068 wireDecode(const Block& wire) final
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070069 {
70 if (wire.type() != 128)
Junxiao Shid97c9532017-04-27 16:17:04 +000071 BOOST_THROW_EXCEPTION(tlv::Error("Expecting TLV type 128"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070072 }
73};
74
75static Authorization
76makeTestAuthorization()
77{
78 return [] (const Name& prefix,
79 const Interest& interest,
80 const ControlParameters* params,
81 AcceptContinuation accept,
82 RejectContinuation reject) {
83 if (interest.getName()[-1] == name::Component("valid")) {
84 accept("");
85 }
86 else {
87 if (interest.getName()[-1] == name::Component("silent")) {
88 reject(RejectReply::SILENT);
89 }
90 else {
91 reject(RejectReply::STATUS403);
92 }
93 }
94 };
95}
96
Junxiao Shid97c9532017-04-27 16:17:04 +000097BOOST_AUTO_TEST_SUITE(Mgmt)
98BOOST_FIXTURE_TEST_SUITE(TestDispatcher, DispatcherFixture)
99
100BOOST_AUTO_TEST_CASE(Basic)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700101{
102 BOOST_CHECK_NO_THROW(dispatcher
103 .addControlCommand<VoidParameters>("test/1", makeAcceptAllAuthorization(),
104 bind([] { return true; }),
105 bind([]{})));
106 BOOST_CHECK_NO_THROW(dispatcher
107 .addControlCommand<VoidParameters>("test/2", makeAcceptAllAuthorization(),
108 bind([] { return true; }),
109 bind([]{})));
110
111 BOOST_CHECK_THROW(dispatcher
112 .addControlCommand<VoidParameters>("test", makeAcceptAllAuthorization(),
113 bind([] { return true; }),
114 bind([]{})),
115 std::out_of_range);
116
117 BOOST_CHECK_NO_THROW(dispatcher.addStatusDataset("status/1",
118 makeAcceptAllAuthorization(), bind([]{})));
119 BOOST_CHECK_NO_THROW(dispatcher.addStatusDataset("status/2",
120 makeAcceptAllAuthorization(), bind([]{})));
121 BOOST_CHECK_THROW(dispatcher.addStatusDataset("status",
122 makeAcceptAllAuthorization(), bind([]{})),
123 std::out_of_range);
124
125 BOOST_CHECK_NO_THROW(dispatcher.addNotificationStream("stream/1"));
126 BOOST_CHECK_NO_THROW(dispatcher.addNotificationStream("stream/2"));
127 BOOST_CHECK_THROW(dispatcher.addNotificationStream("stream"), std::out_of_range);
128
129
130 BOOST_CHECK_NO_THROW(dispatcher.addTopPrefix("/root/1"));
131 BOOST_CHECK_NO_THROW(dispatcher.addTopPrefix("/root/2"));
132 BOOST_CHECK_THROW(dispatcher.addTopPrefix("/root"), std::out_of_range);
133
134 BOOST_CHECK_THROW(dispatcher
135 .addControlCommand<VoidParameters>("test/3", makeAcceptAllAuthorization(),
136 bind([] { return true; }),
137 bind([]{})),
138 std::domain_error);
139
140 BOOST_CHECK_THROW(dispatcher.addStatusDataset("status/3",
141 makeAcceptAllAuthorization(), bind([]{})),
142 std::domain_error);
143
144 BOOST_CHECK_THROW(dispatcher.addNotificationStream("stream/3"), std::domain_error);
145}
146
Junxiao Shid97c9532017-04-27 16:17:04 +0000147BOOST_AUTO_TEST_CASE(AddRemoveTopPrefix)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700148{
149 std::map<std::string, size_t> nCallbackCalled;
150 dispatcher
151 .addControlCommand<VoidParameters>("test/1", makeAcceptAllAuthorization(),
152 bind([] { return true; }),
153 bind([&nCallbackCalled] { ++nCallbackCalled["test/1"]; }));
154
155 dispatcher
156 .addControlCommand<VoidParameters>("test/2", makeAcceptAllAuthorization(),
157 bind([] { return true; }),
158 bind([&nCallbackCalled] { ++nCallbackCalled["test/2"]; }));
159
Junxiao Shi85d90832016-08-04 03:19:46 +0000160 face.receive(*makeInterest("/root/1/test/1/%80%00"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700161 advanceClocks(time::milliseconds(1));
162 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 0);
163 BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 0);
164
165 dispatcher.addTopPrefix("/root/1");
166 advanceClocks(time::milliseconds(1));
167
Junxiao Shi85d90832016-08-04 03:19:46 +0000168 face.receive(*makeInterest("/root/1/test/1/%80%00"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700169 advanceClocks(time::milliseconds(1));
170 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 1);
171 BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 0);
172
Junxiao Shi85d90832016-08-04 03:19:46 +0000173 face.receive(*makeInterest("/root/1/test/2/%80%00"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700174 advanceClocks(time::milliseconds(1));
175 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 1);
176 BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 1);
177
Junxiao Shi85d90832016-08-04 03:19:46 +0000178 face.receive(*makeInterest("/root/2/test/1/%80%00"));
179 face.receive(*makeInterest("/root/2/test/2/%80%00"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700180 advanceClocks(time::milliseconds(1));
181 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 1);
182 BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 1);
183
184 dispatcher.addTopPrefix("/root/2");
185 advanceClocks(time::milliseconds(1));
186
Junxiao Shi85d90832016-08-04 03:19:46 +0000187 face.receive(*makeInterest("/root/1/test/1/%80%00"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700188 advanceClocks(time::milliseconds(1));
189 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 2);
190
Junxiao Shi85d90832016-08-04 03:19:46 +0000191 face.receive(*makeInterest("/root/2/test/1/%80%00"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700192 advanceClocks(time::milliseconds(1));
193 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 3);
194
195 dispatcher.removeTopPrefix("/root/1");
196 advanceClocks(time::milliseconds(1));
197
Junxiao Shi85d90832016-08-04 03:19:46 +0000198 face.receive(*makeInterest("/root/1/test/1/%80%00"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700199 advanceClocks(time::milliseconds(1));
200 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 3);
201
Junxiao Shi85d90832016-08-04 03:19:46 +0000202 face.receive(*makeInterest("/root/2/test/1/%80%00"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700203 advanceClocks(time::milliseconds(1));
204 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 4);
205}
206
Junxiao Shid97c9532017-04-27 16:17:04 +0000207BOOST_AUTO_TEST_CASE(ControlCommand)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700208{
209 size_t nCallbackCalled = 0;
210 dispatcher
211 .addControlCommand<VoidParameters>("test",
212 makeTestAuthorization(),
213 bind([] { return true; }),
214 bind([&nCallbackCalled] { ++nCallbackCalled; }));
215
216 dispatcher.addTopPrefix("/root");
217 advanceClocks(time::milliseconds(1));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800218 face.sentData.clear();
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700219
Junxiao Shi85d90832016-08-04 03:19:46 +0000220 face.receive(*makeInterest("/root/test/%80%00")); // returns 403
221 face.receive(*makeInterest("/root/test/%80%00/invalid")); // returns 403
222 face.receive(*makeInterest("/root/test/%80%00/silent")); // silently ignored
223 face.receive(*makeInterest("/root/test/.../invalid")); // silently ignored (wrong format)
224 face.receive(*makeInterest("/root/test/.../valid")); // silently ignored (wrong format)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700225 advanceClocks(time::milliseconds(1), 20);
226 BOOST_CHECK_EQUAL(nCallbackCalled, 0);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800227 BOOST_CHECK_EQUAL(face.sentData.size(), 2);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700228
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800229 BOOST_CHECK(face.sentData[0].getContentType() == tlv::ContentType_Blob);
230 BOOST_CHECK_EQUAL(ControlResponse(face.sentData[0].getContent().blockFromValue()).getCode(), 403);
231 BOOST_CHECK(face.sentData[1].getContentType() == tlv::ContentType_Blob);
232 BOOST_CHECK_EQUAL(ControlResponse(face.sentData[1].getContent().blockFromValue()).getCode(), 403);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700233
Junxiao Shi85d90832016-08-04 03:19:46 +0000234 face.receive(*makeInterest("/root/test/%80%00/valid"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700235 advanceClocks(time::milliseconds(1), 10);
236 BOOST_CHECK_EQUAL(nCallbackCalled, 1);
237}
238
Junxiao Shid97c9532017-04-27 16:17:04 +0000239class StatefulParameters : public mgmt::ControlParameters
240{
241public:
242 explicit
243 StatefulParameters(const Block& wire)
244 {
245 wireDecode(wire);
246 }
247
248 Block
249 wireEncode() const final
250 {
251 return Block();
252 }
253
254 void
255 wireDecode(const Block& wire) final
256 {
257 m_state = EXPECTED_STATE;
258 }
259
260 bool
261 check() const
262 {
263 return m_state == EXPECTED_STATE;
264 }
265
266private:
267 static constexpr int EXPECTED_STATE = 12602;
268 int m_state = 0;
269};
270
271BOOST_AUTO_TEST_CASE(ControlCommandAsyncAuthorization) // Bug 4059
272{
273 AcceptContinuation authorizationAccept;
274 auto authorization =
275 [&authorizationAccept] (const Name& prefix, const Interest& interest, const ControlParameters* params,
276 AcceptContinuation accept, RejectContinuation reject) {
277 authorizationAccept = accept;
278 };
279
280 auto validateParameters =
281 [] (const ControlParameters& params) {
282 return dynamic_cast<const StatefulParameters&>(params).check();
283 };
284
285 size_t nCallbackCalled = 0;
286 dispatcher
287 .addControlCommand<StatefulParameters>("test",
288 authorization,
289 validateParameters,
290 bind([&nCallbackCalled] { ++nCallbackCalled; }));
291
292 dispatcher.addTopPrefix("/root");
293 advanceClocks(time::milliseconds(1));
294
295 face.receive(*makeInterest("/root/test/%80%00"));
296 BOOST_CHECK_EQUAL(nCallbackCalled, 0);
297 BOOST_REQUIRE(authorizationAccept != nullptr);
298
299 advanceClocks(time::milliseconds(1));
300 authorizationAccept("");
301 advanceClocks(time::milliseconds(1));
302 BOOST_CHECK_EQUAL(nCallbackCalled, 1);
303}
304
305BOOST_AUTO_TEST_CASE(StatusDataset)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700306{
Davide Pesaventob10024c2017-09-22 01:36:44 -0400307 const uint8_t smallBuf[] = {0x81, 0x01, 0x01};
308 const Block smallBlock(smallBuf, sizeof(smallBuf));
309 Block largeBlock;
310 {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700311 EncodingBuffer encoder;
312 for (size_t i = 0; i < 2500; ++i) {
313 encoder.prependByte(1);
314 }
315 encoder.prependVarNumber(2500);
316 encoder.prependVarNumber(129);
Davide Pesaventob10024c2017-09-22 01:36:44 -0400317 largeBlock = encoder.block();
318 }
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700319
320 dispatcher.addStatusDataset("test/small",
321 makeTestAuthorization(),
Davide Pesaventob10024c2017-09-22 01:36:44 -0400322 [&smallBlock] (const Name& prefix, const Interest& interest,
323 StatusDatasetContext& context) {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700324 context.append(smallBlock);
325 context.append(smallBlock);
326 context.append(smallBlock);
327 context.end();
328 });
329
330 dispatcher.addStatusDataset("test/large",
331 makeTestAuthorization(),
Davide Pesaventob10024c2017-09-22 01:36:44 -0400332 [&largeBlock] (const Name& prefix, const Interest& interest,
333 StatusDatasetContext& context) {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700334 context.append(largeBlock);
335 context.append(largeBlock);
336 context.append(largeBlock);
337 context.end();
338 });
339
340 dispatcher.addStatusDataset("test/reject",
341 makeTestAuthorization(),
342 [] (const Name& prefix, const Interest& interest,
Junxiao Shif65a3362015-09-06 20:54:54 -0700343 StatusDatasetContext& context) {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700344 context.reject();
345 });
346
347 dispatcher.addTopPrefix("/root");
348 advanceClocks(time::milliseconds(1));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800349 face.sentData.clear();
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700350
Junxiao Shi85d90832016-08-04 03:19:46 +0000351 face.receive(*makeInterest("/root/test/small/%80%00")); // returns 403
352 face.receive(*makeInterest("/root/test/small/%80%00/invalid")); // returns 403
353 face.receive(*makeInterest("/root/test/small/%80%00/silent")); // silently ignored
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700354 advanceClocks(time::milliseconds(1), 20);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800355 BOOST_CHECK_EQUAL(face.sentData.size(), 2);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700356
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800357 BOOST_CHECK(face.sentData[0].getContentType() == tlv::ContentType_Blob);
358 BOOST_CHECK_EQUAL(ControlResponse(face.sentData[0].getContent().blockFromValue()).getCode(), 403);
359 BOOST_CHECK(face.sentData[1].getContentType() == tlv::ContentType_Blob);
360 BOOST_CHECK_EQUAL(ControlResponse(face.sentData[1].getContent().blockFromValue()).getCode(), 403);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700361
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800362 face.sentData.clear();
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800363
Junxiao Shi85d90832016-08-04 03:19:46 +0000364 auto interestSmall = *makeInterest("/root/test/small/valid");
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800365 face.receive(interestSmall);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700366 advanceClocks(time::milliseconds(1), 10);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800367
368 // one data packet is generated and sent to both places
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800369 BOOST_CHECK_EQUAL(face.sentData.size(), 1);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800370 BOOST_CHECK_EQUAL(storage.size(), 1);
371
372 auto fetchedData = storage.find(interestSmall);
373 BOOST_REQUIRE(fetchedData != nullptr);
374 BOOST_CHECK(face.sentData[0].wireEncode() == fetchedData->wireEncode());
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700375
Junxiao Shi85d90832016-08-04 03:19:46 +0000376 face.receive(*makeInterest(Name("/root/test/small/valid").appendVersion(10))); // should be ignored
377 face.receive(*makeInterest(Name("/root/test/small/valid").appendSegment(20))); // should be ignored
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700378 advanceClocks(time::milliseconds(1), 10);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800379 BOOST_CHECK_EQUAL(face.sentData.size(), 1);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800380 BOOST_CHECK_EQUAL(storage.size(), 1);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700381
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800382 Block content = face.sentData[0].getContent();
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700383 BOOST_CHECK_NO_THROW(content.parse());
384
385 BOOST_CHECK_EQUAL(content.elements().size(), 3);
386 BOOST_CHECK(content.elements()[0] == smallBlock);
387 BOOST_CHECK(content.elements()[1] == smallBlock);
388 BOOST_CHECK(content.elements()[2] == smallBlock);
389
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800390 storage.erase("/", true); // clear the storage
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800391 face.sentData.clear();
Junxiao Shi85d90832016-08-04 03:19:46 +0000392 face.receive(*makeInterest("/root/test/large/valid"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700393 advanceClocks(time::milliseconds(1), 10);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700394
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800395 // two data packets are generated, the first one will be sent to both places
396 // while the second one will only be inserted into the in-memory storage
397 BOOST_CHECK_EQUAL(face.sentData.size(), 1);
398 BOOST_CHECK_EQUAL(storage.size(), 2);
399
400 // segment0 should be sent through the face
401 const auto& component = face.sentData[0].getName().at(-1);
402 BOOST_CHECK(component.isSegment());
403 BOOST_CHECK_EQUAL(component.toSegment(), 0);
404
405 std::vector<Data> dataInStorage;
406 std::copy(storage.begin(), storage.end(), std::back_inserter(dataInStorage));
407
408 // the Data sent through the face should be the same as the first Data in the storage
409 BOOST_CHECK_EQUAL(face.sentData[0].getName(), dataInStorage[0].getName());
410 BOOST_CHECK(face.sentData[0].getContent() == dataInStorage[0].getContent());
411
412 content = [&dataInStorage] () -> Block {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700413 EncodingBuffer encoder;
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800414 size_t valueLength = encoder.prependByteArray(dataInStorage[1].getContent().value(),
415 dataInStorage[1].getContent().value_size());
416 valueLength += encoder.prependByteArray(dataInStorage[0].getContent().value(),
417 dataInStorage[0].getContent().value_size());
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700418 encoder.prependVarNumber(valueLength);
419 encoder.prependVarNumber(tlv::Content);
420 return encoder.block();
421 }();
422
423 BOOST_CHECK_NO_THROW(content.parse());
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700424 BOOST_CHECK_EQUAL(content.elements().size(), 3);
425 BOOST_CHECK(content.elements()[0] == largeBlock);
426 BOOST_CHECK(content.elements()[1] == largeBlock);
427 BOOST_CHECK(content.elements()[2] == largeBlock);
428
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800429 storage.erase("/", true);// clear the storage
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800430 face.sentData.clear();
Junxiao Shi85d90832016-08-04 03:19:46 +0000431 face.receive(*makeInterest("/root/test/reject/%80%00/valid")); // returns nack
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700432 advanceClocks(time::milliseconds(1));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800433 BOOST_CHECK_EQUAL(face.sentData.size(), 1);
434 BOOST_CHECK(face.sentData[0].getContentType() == tlv::ContentType_Nack);
435 BOOST_CHECK_EQUAL(ControlResponse(face.sentData[0].getContent().blockFromValue()).getCode(), 400);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800436 BOOST_CHECK_EQUAL(storage.size(), 0); // the nack packet will not be inserted into the in-memory storage
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700437}
438
Junxiao Shid97c9532017-04-27 16:17:04 +0000439BOOST_AUTO_TEST_CASE(NotificationStream)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700440{
Davide Pesaventob10024c2017-09-22 01:36:44 -0400441 const uint8_t buf[] = {0x82, 0x01, 0x02};
442 const Block block(buf, sizeof(buf));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700443 auto post = dispatcher.addNotificationStream("test");
444
445 post(block);
446 advanceClocks(time::milliseconds(1));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800447 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700448
449 dispatcher.addTopPrefix("/root");
450 advanceClocks(time::milliseconds(1));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800451 face.sentData.clear();
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700452
453 post(block);
454 advanceClocks(time::milliseconds(1));
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800455 BOOST_CHECK_EQUAL(face.sentData.size(), 1);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800456 BOOST_CHECK_EQUAL(storage.size(), 1);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700457
458 post(block);
459 post(block);
460 post(block);
461 advanceClocks(time::milliseconds(1), 10);
462
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800463 BOOST_CHECK_EQUAL(face.sentData.size(), 4);
464 BOOST_CHECK_EQUAL(face.sentData[0].getName(), "/root/test/%FE%00");
465 BOOST_CHECK_EQUAL(face.sentData[1].getName(), "/root/test/%FE%01");
466 BOOST_CHECK_EQUAL(face.sentData[2].getName(), "/root/test/%FE%02");
467 BOOST_CHECK_EQUAL(face.sentData[3].getName(), "/root/test/%FE%03");
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700468
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800469 BOOST_CHECK(face.sentData[0].getContent().blockFromValue() == block);
470 BOOST_CHECK(face.sentData[1].getContent().blockFromValue() == block);
471 BOOST_CHECK(face.sentData[2].getContent().blockFromValue() == block);
472 BOOST_CHECK(face.sentData[3].getContent().blockFromValue() == block);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800473
474 // each version of notification will be sent to both places
475 std::vector<Data> dataInStorage;
476 std::copy(storage.begin(), storage.end(), std::back_inserter(dataInStorage));
477 BOOST_CHECK_EQUAL(dataInStorage.size(), 4);
478 BOOST_CHECK_EQUAL(dataInStorage[0].getName(), "/root/test/%FE%00");
479 BOOST_CHECK_EQUAL(dataInStorage[1].getName(), "/root/test/%FE%01");
480 BOOST_CHECK_EQUAL(dataInStorage[2].getName(), "/root/test/%FE%02");
481 BOOST_CHECK_EQUAL(dataInStorage[3].getName(), "/root/test/%FE%03");
482
483 BOOST_CHECK(dataInStorage[0].getContent().blockFromValue() == block);
484 BOOST_CHECK(dataInStorage[1].getContent().blockFromValue() == block);
485 BOOST_CHECK(dataInStorage[2].getContent().blockFromValue() == block);
486 BOOST_CHECK(dataInStorage[3].getContent().blockFromValue() == block);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700487}
488
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800489BOOST_AUTO_TEST_SUITE_END() // TestDispatcher
490BOOST_AUTO_TEST_SUITE_END() // Mgmt
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700491
492} // namespace tests
493} // namespace mgmt
494} // namespace ndn