blob: 9087179c190c67ca1765d932994a8c070d3cd90a [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/*
Davide Pesavento0c526032024-01-31 21:14:01 -05003 * Copyright (c) 2013-2024 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
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/mgmt/dispatcher.hpp"
23#include "ndn-cxx/mgmt/nfd/control-parameters.hpp"
24#include "ndn-cxx/util/dummy-client-face.hpp"
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070025
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050026#include "tests/test-common.hpp"
27#include "tests/unit/io-key-chain-fixture.hpp"
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070028
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040029namespace ndn::tests {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070030
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040031using namespace ndn::mgmt;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070032
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050033class DispatcherFixture : public IoKeyChainFixture
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070034{
35public:
36 DispatcherFixture()
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050037 : face(m_io, m_keyChain, {true, true})
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080038 , dispatcher(face, m_keyChain, security::SigningInfo())
Yanbiao Li4b4f7542016-03-11 02:04:43 +080039 , storage(dispatcher.m_storage)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070040 {
41 }
42
43public:
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040044 DummyClientFace face;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070045 mgmt::Dispatcher dispatcher;
Junxiao Shic542f632017-07-18 14:20:32 +000046 InMemoryStorageFifo& storage;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070047};
48
49class VoidParameters : public mgmt::ControlParameters
50{
51public:
52 explicit
53 VoidParameters(const Block& wire)
54 {
55 wireDecode(wire);
56 }
57
Junxiao Shid97c9532017-04-27 16:17:04 +000058 Block
Davide Pesaventoaa82eb62016-04-22 19:08:40 +020059 wireEncode() const final
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070060 {
61 return Block(128);
62 }
63
Junxiao Shid97c9532017-04-27 16:17:04 +000064 void
Davide Pesaventoaa82eb62016-04-22 19:08:40 +020065 wireDecode(const Block& wire) final
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070066 {
67 if (wire.type() != 128)
Davide Pesavento923ba442019-02-12 22:00:38 -050068 NDN_THROW(tlv::Error("Expecting TLV type 128"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070069 }
70};
71
72static Authorization
73makeTestAuthorization()
74{
Davide Pesavento3c34ec12021-03-28 21:50:06 -040075 return [] (const Name&, const Interest& interest, const ControlParameters*,
76 AcceptContinuation accept, RejectContinuation reject) {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070077 if (interest.getName()[-1] == name::Component("valid")) {
78 accept("");
79 }
80 else {
81 if (interest.getName()[-1] == name::Component("silent")) {
82 reject(RejectReply::SILENT);
83 }
84 else {
85 reject(RejectReply::STATUS403);
86 }
87 }
88 };
89}
90
Junxiao Shid97c9532017-04-27 16:17:04 +000091BOOST_AUTO_TEST_SUITE(Mgmt)
92BOOST_FIXTURE_TEST_SUITE(TestDispatcher, DispatcherFixture)
93
94BOOST_AUTO_TEST_CASE(Basic)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070095{
96 BOOST_CHECK_NO_THROW(dispatcher
97 .addControlCommand<VoidParameters>("test/1", makeAcceptAllAuthorization(),
Davide Pesavento152ef442023-04-22 02:02:29 -040098 std::bind([] { return true; }),
99 std::bind([]{})));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700100 BOOST_CHECK_NO_THROW(dispatcher
101 .addControlCommand<VoidParameters>("test/2", makeAcceptAllAuthorization(),
Davide Pesavento152ef442023-04-22 02:02:29 -0400102 std::bind([] { return true; }),
103 std::bind([]{})));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700104
105 BOOST_CHECK_THROW(dispatcher
106 .addControlCommand<VoidParameters>("test", makeAcceptAllAuthorization(),
Davide Pesavento152ef442023-04-22 02:02:29 -0400107 std::bind([] { return true; }),
108 std::bind([]{})),
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700109 std::out_of_range);
110
111 BOOST_CHECK_NO_THROW(dispatcher.addStatusDataset("status/1",
Davide Pesavento152ef442023-04-22 02:02:29 -0400112 makeAcceptAllAuthorization(), std::bind([]{})));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700113 BOOST_CHECK_NO_THROW(dispatcher.addStatusDataset("status/2",
Davide Pesavento152ef442023-04-22 02:02:29 -0400114 makeAcceptAllAuthorization(), std::bind([]{})));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700115 BOOST_CHECK_THROW(dispatcher.addStatusDataset("status",
Davide Pesavento152ef442023-04-22 02:02:29 -0400116 makeAcceptAllAuthorization(), std::bind([]{})),
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700117 std::out_of_range);
118
119 BOOST_CHECK_NO_THROW(dispatcher.addNotificationStream("stream/1"));
120 BOOST_CHECK_NO_THROW(dispatcher.addNotificationStream("stream/2"));
121 BOOST_CHECK_THROW(dispatcher.addNotificationStream("stream"), std::out_of_range);
122
123
124 BOOST_CHECK_NO_THROW(dispatcher.addTopPrefix("/root/1"));
125 BOOST_CHECK_NO_THROW(dispatcher.addTopPrefix("/root/2"));
126 BOOST_CHECK_THROW(dispatcher.addTopPrefix("/root"), std::out_of_range);
127
128 BOOST_CHECK_THROW(dispatcher
129 .addControlCommand<VoidParameters>("test/3", makeAcceptAllAuthorization(),
Davide Pesavento152ef442023-04-22 02:02:29 -0400130 std::bind([] { return true; }),
131 std::bind([]{})),
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700132 std::domain_error);
133
134 BOOST_CHECK_THROW(dispatcher.addStatusDataset("status/3",
Davide Pesavento152ef442023-04-22 02:02:29 -0400135 makeAcceptAllAuthorization(), std::bind([]{})),
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700136 std::domain_error);
137
138 BOOST_CHECK_THROW(dispatcher.addNotificationStream("stream/3"), std::domain_error);
139}
140
Junxiao Shid97c9532017-04-27 16:17:04 +0000141BOOST_AUTO_TEST_CASE(AddRemoveTopPrefix)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700142{
143 std::map<std::string, size_t> nCallbackCalled;
144 dispatcher
145 .addControlCommand<VoidParameters>("test/1", makeAcceptAllAuthorization(),
Davide Pesavento152ef442023-04-22 02:02:29 -0400146 std::bind([] { return true; }),
147 std::bind([&nCallbackCalled] { ++nCallbackCalled["test/1"]; }));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700148
149 dispatcher
150 .addControlCommand<VoidParameters>("test/2", makeAcceptAllAuthorization(),
Davide Pesavento152ef442023-04-22 02:02:29 -0400151 std::bind([] { return true; }),
152 std::bind([&nCallbackCalled] { ++nCallbackCalled["test/2"]; }));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700153
Junxiao Shi85d90832016-08-04 03:19:46 +0000154 face.receive(*makeInterest("/root/1/test/1/%80%00"));
Davide Pesavento0f830802018-01-16 23:58:58 -0500155 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700156 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 0);
157 BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 0);
158
159 dispatcher.addTopPrefix("/root/1");
Davide Pesavento0f830802018-01-16 23:58:58 -0500160 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700161
Junxiao Shi85d90832016-08-04 03:19:46 +0000162 face.receive(*makeInterest("/root/1/test/1/%80%00"));
Davide Pesavento0f830802018-01-16 23:58:58 -0500163 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700164 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 1);
165 BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 0);
166
Junxiao Shi85d90832016-08-04 03:19:46 +0000167 face.receive(*makeInterest("/root/1/test/2/%80%00"));
Davide Pesavento0f830802018-01-16 23:58:58 -0500168 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700169 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 1);
170 BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 1);
171
Junxiao Shi85d90832016-08-04 03:19:46 +0000172 face.receive(*makeInterest("/root/2/test/1/%80%00"));
173 face.receive(*makeInterest("/root/2/test/2/%80%00"));
Davide Pesavento0f830802018-01-16 23:58:58 -0500174 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700175 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 1);
176 BOOST_CHECK_EQUAL(nCallbackCalled["test/2"], 1);
177
178 dispatcher.addTopPrefix("/root/2");
Davide Pesavento0f830802018-01-16 23:58:58 -0500179 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700180
Junxiao Shi85d90832016-08-04 03:19:46 +0000181 face.receive(*makeInterest("/root/1/test/1/%80%00"));
Davide Pesavento0f830802018-01-16 23:58:58 -0500182 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700183 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 2);
184
Junxiao Shi85d90832016-08-04 03:19:46 +0000185 face.receive(*makeInterest("/root/2/test/1/%80%00"));
Davide Pesavento0f830802018-01-16 23:58:58 -0500186 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700187 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 3);
188
189 dispatcher.removeTopPrefix("/root/1");
Davide Pesavento0f830802018-01-16 23:58:58 -0500190 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700191
Junxiao Shi85d90832016-08-04 03:19:46 +0000192 face.receive(*makeInterest("/root/1/test/1/%80%00"));
Davide Pesavento0f830802018-01-16 23:58:58 -0500193 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700194 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 3);
195
Junxiao Shi85d90832016-08-04 03:19:46 +0000196 face.receive(*makeInterest("/root/2/test/1/%80%00"));
Davide Pesavento0f830802018-01-16 23:58:58 -0500197 advanceClocks(1_ms);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700198 BOOST_CHECK_EQUAL(nCallbackCalled["test/1"], 4);
199}
200
Junxiao Shid97c9532017-04-27 16:17:04 +0000201BOOST_AUTO_TEST_CASE(ControlCommand)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700202{
203 size_t nCallbackCalled = 0;
204 dispatcher
205 .addControlCommand<VoidParameters>("test",
206 makeTestAuthorization(),
Davide Pesavento152ef442023-04-22 02:02:29 -0400207 std::bind([] { return true; }),
208 std::bind([&nCallbackCalled] { ++nCallbackCalled; }));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700209
210 dispatcher.addTopPrefix("/root");
Davide Pesavento0f830802018-01-16 23:58:58 -0500211 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800212 face.sentData.clear();
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700213
Junxiao Shi85d90832016-08-04 03:19:46 +0000214 face.receive(*makeInterest("/root/test/%80%00")); // returns 403
215 face.receive(*makeInterest("/root/test/%80%00/invalid")); // returns 403
216 face.receive(*makeInterest("/root/test/%80%00/silent")); // silently ignored
217 face.receive(*makeInterest("/root/test/.../invalid")); // silently ignored (wrong format)
218 face.receive(*makeInterest("/root/test/.../valid")); // silently ignored (wrong format)
Davide Pesavento0f830802018-01-16 23:58:58 -0500219 advanceClocks(1_ms, 20);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700220 BOOST_CHECK_EQUAL(nCallbackCalled, 0);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800221 BOOST_CHECK_EQUAL(face.sentData.size(), 2);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700222
Junxiao Shi72c0c642018-04-20 15:41:09 +0000223 BOOST_CHECK_EQUAL(face.sentData[0].getContentType(), tlv::ContentType_Blob);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800224 BOOST_CHECK_EQUAL(ControlResponse(face.sentData[0].getContent().blockFromValue()).getCode(), 403);
Junxiao Shi72c0c642018-04-20 15:41:09 +0000225 BOOST_CHECK_EQUAL(face.sentData[1].getContentType(), tlv::ContentType_Blob);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800226 BOOST_CHECK_EQUAL(ControlResponse(face.sentData[1].getContent().blockFromValue()).getCode(), 403);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700227
Junxiao Shi85d90832016-08-04 03:19:46 +0000228 face.receive(*makeInterest("/root/test/%80%00/valid"));
Davide Pesavento0f830802018-01-16 23:58:58 -0500229 advanceClocks(1_ms, 10);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700230 BOOST_CHECK_EQUAL(nCallbackCalled, 1);
231}
232
Junxiao Shid97c9532017-04-27 16:17:04 +0000233class StatefulParameters : public mgmt::ControlParameters
234{
235public:
236 explicit
237 StatefulParameters(const Block& wire)
238 {
239 wireDecode(wire);
240 }
241
242 Block
243 wireEncode() const final
244 {
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500245 return {};
Junxiao Shid97c9532017-04-27 16:17:04 +0000246 }
247
248 void
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400249 wireDecode(const Block&) final
Junxiao Shid97c9532017-04-27 16:17:04 +0000250 {
251 m_state = EXPECTED_STATE;
252 }
253
254 bool
255 check() const
256 {
257 return m_state == EXPECTED_STATE;
258 }
259
260private:
261 static constexpr int EXPECTED_STATE = 12602;
262 int m_state = 0;
263};
264
Davide Pesavento0c526032024-01-31 21:14:01 -0500265BOOST_AUTO_TEST_CASE(ControlCommandAsyncAuthorization,
266 * ut::description("test for bug #4059"))
Junxiao Shid97c9532017-04-27 16:17:04 +0000267{
268 AcceptContinuation authorizationAccept;
269 auto authorization =
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400270 [&authorizationAccept] (const Name&, const Interest&, const ControlParameters*,
271 AcceptContinuation accept, RejectContinuation) {
272 authorizationAccept = std::move(accept);
Junxiao Shid97c9532017-04-27 16:17:04 +0000273 };
274
275 auto validateParameters =
276 [] (const ControlParameters& params) {
277 return dynamic_cast<const StatefulParameters&>(params).check();
278 };
279
280 size_t nCallbackCalled = 0;
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400281 dispatcher.addControlCommand<StatefulParameters>("test", authorization, validateParameters,
Davide Pesavento152ef442023-04-22 02:02:29 -0400282 std::bind([&nCallbackCalled] { ++nCallbackCalled; }));
Junxiao Shid97c9532017-04-27 16:17:04 +0000283
284 dispatcher.addTopPrefix("/root");
Davide Pesavento0f830802018-01-16 23:58:58 -0500285 advanceClocks(1_ms);
Junxiao Shid97c9532017-04-27 16:17:04 +0000286
287 face.receive(*makeInterest("/root/test/%80%00"));
288 BOOST_CHECK_EQUAL(nCallbackCalled, 0);
289 BOOST_REQUIRE(authorizationAccept != nullptr);
290
Davide Pesavento0f830802018-01-16 23:58:58 -0500291 advanceClocks(1_ms);
Junxiao Shid97c9532017-04-27 16:17:04 +0000292 authorizationAccept("");
Davide Pesavento0f830802018-01-16 23:58:58 -0500293 advanceClocks(1_ms);
Junxiao Shid97c9532017-04-27 16:17:04 +0000294 BOOST_CHECK_EQUAL(nCallbackCalled, 1);
295}
296
297BOOST_AUTO_TEST_CASE(StatusDataset)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700298{
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500299 const Block smallBlock({0x81, 0x01, 0x01});
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400300 const Block largeBlock = [] {
301 Block b(129, std::make_shared<const Buffer>(3000));
302 b.encode();
303 return b;
304 }();
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700305
306 dispatcher.addStatusDataset("test/small",
307 makeTestAuthorization(),
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400308 [&smallBlock] (const Name&, const Interest&,
Davide Pesaventob10024c2017-09-22 01:36:44 -0400309 StatusDatasetContext& context) {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700310 context.append(smallBlock);
311 context.append(smallBlock);
312 context.append(smallBlock);
313 context.end();
314 });
315
316 dispatcher.addStatusDataset("test/large",
317 makeTestAuthorization(),
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400318 [&largeBlock] (const Name&, const Interest&,
Davide Pesaventob10024c2017-09-22 01:36:44 -0400319 StatusDatasetContext& context) {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700320 context.append(largeBlock);
321 context.append(largeBlock);
322 context.append(largeBlock);
323 context.end();
324 });
325
326 dispatcher.addStatusDataset("test/reject",
327 makeTestAuthorization(),
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400328 [] (const Name&, const Interest&, StatusDatasetContext& context) {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700329 context.reject();
330 });
331
332 dispatcher.addTopPrefix("/root");
Davide Pesavento0f830802018-01-16 23:58:58 -0500333 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800334 face.sentData.clear();
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700335
Junxiao Shi85d90832016-08-04 03:19:46 +0000336 face.receive(*makeInterest("/root/test/small/%80%00")); // returns 403
337 face.receive(*makeInterest("/root/test/small/%80%00/invalid")); // returns 403
338 face.receive(*makeInterest("/root/test/small/%80%00/silent")); // silently ignored
Davide Pesavento0f830802018-01-16 23:58:58 -0500339 advanceClocks(1_ms, 20);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700340
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400341 BOOST_REQUIRE_EQUAL(face.sentData.size(), 2);
Junxiao Shi72c0c642018-04-20 15:41:09 +0000342 BOOST_CHECK_EQUAL(face.sentData[0].getContentType(), tlv::ContentType_Blob);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800343 BOOST_CHECK_EQUAL(ControlResponse(face.sentData[0].getContent().blockFromValue()).getCode(), 403);
Junxiao Shi72c0c642018-04-20 15:41:09 +0000344 BOOST_CHECK_EQUAL(face.sentData[1].getContentType(), tlv::ContentType_Blob);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800345 BOOST_CHECK_EQUAL(ControlResponse(face.sentData[1].getContent().blockFromValue()).getCode(), 403);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700346
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800347 face.sentData.clear();
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800348
Junxiao Shib55e5d32018-07-18 13:32:00 -0600349 auto interestSmall = *makeInterest("/root/test/small/valid", true);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800350 face.receive(interestSmall);
Davide Pesavento0f830802018-01-16 23:58:58 -0500351 advanceClocks(1_ms, 10);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800352
353 // one data packet is generated and sent to both places
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400354 BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800355 BOOST_CHECK_EQUAL(storage.size(), 1);
356
357 auto fetchedData = storage.find(interestSmall);
358 BOOST_REQUIRE(fetchedData != nullptr);
Junxiao Shi72c0c642018-04-20 15:41:09 +0000359 BOOST_CHECK_EQUAL(face.sentData[0].wireEncode(), fetchedData->wireEncode());
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700360
Junxiao Shi85d90832016-08-04 03:19:46 +0000361 face.receive(*makeInterest(Name("/root/test/small/valid").appendVersion(10))); // should be ignored
362 face.receive(*makeInterest(Name("/root/test/small/valid").appendSegment(20))); // should be ignored
Davide Pesavento0f830802018-01-16 23:58:58 -0500363 advanceClocks(1_ms, 10);
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400364 BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800365 BOOST_CHECK_EQUAL(storage.size(), 1);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700366
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800367 Block content = face.sentData[0].getContent();
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700368 BOOST_CHECK_NO_THROW(content.parse());
369
Junxiao Shi72c0c642018-04-20 15:41:09 +0000370 BOOST_REQUIRE_EQUAL(content.elements().size(), 3);
371 BOOST_CHECK_EQUAL(content.elements()[0], smallBlock);
372 BOOST_CHECK_EQUAL(content.elements()[1], smallBlock);
373 BOOST_CHECK_EQUAL(content.elements()[2], smallBlock);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700374
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800375 storage.erase("/", true); // clear the storage
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800376 face.sentData.clear();
Junxiao Shi85d90832016-08-04 03:19:46 +0000377 face.receive(*makeInterest("/root/test/large/valid"));
Davide Pesavento0f830802018-01-16 23:58:58 -0500378 advanceClocks(1_ms, 10);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700379
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800380 // two data packets are generated, the first one will be sent to both places
381 // while the second one will only be inserted into the in-memory storage
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400382 BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
383 BOOST_REQUIRE_EQUAL(storage.size(), 2);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800384
385 // segment0 should be sent through the face
386 const auto& component = face.sentData[0].getName().at(-1);
387 BOOST_CHECK(component.isSegment());
388 BOOST_CHECK_EQUAL(component.toSegment(), 0);
389
390 std::vector<Data> dataInStorage;
391 std::copy(storage.begin(), storage.end(), std::back_inserter(dataInStorage));
392
393 // the Data sent through the face should be the same as the first Data in the storage
394 BOOST_CHECK_EQUAL(face.sentData[0].getName(), dataInStorage[0].getName());
Junxiao Shi72c0c642018-04-20 15:41:09 +0000395 BOOST_CHECK_EQUAL(face.sentData[0].getContent(), dataInStorage[0].getContent());
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800396
397 content = [&dataInStorage] () -> Block {
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700398 EncodingBuffer encoder;
Davide Pesavento258d51a2022-02-27 21:26:28 -0500399 size_t valueLength = encoder.prependBytes(dataInStorage[1].getContent().value_bytes());
400 valueLength += encoder.prependBytes(dataInStorage[0].getContent().value_bytes());
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700401 encoder.prependVarNumber(valueLength);
402 encoder.prependVarNumber(tlv::Content);
403 return encoder.block();
404 }();
405
406 BOOST_CHECK_NO_THROW(content.parse());
Junxiao Shi72c0c642018-04-20 15:41:09 +0000407 BOOST_REQUIRE_EQUAL(content.elements().size(), 3);
408 BOOST_CHECK_EQUAL(content.elements()[0], largeBlock);
409 BOOST_CHECK_EQUAL(content.elements()[1], largeBlock);
410 BOOST_CHECK_EQUAL(content.elements()[2], largeBlock);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700411
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800412 storage.erase("/", true);// clear the storage
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800413 face.sentData.clear();
Junxiao Shi85d90832016-08-04 03:19:46 +0000414 face.receive(*makeInterest("/root/test/reject/%80%00/valid")); // returns nack
Davide Pesavento0f830802018-01-16 23:58:58 -0500415 advanceClocks(1_ms);
Davide Pesavento3c34ec12021-03-28 21:50:06 -0400416
417 BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
Junxiao Shi72c0c642018-04-20 15:41:09 +0000418 BOOST_CHECK_EQUAL(face.sentData[0].getContentType(), tlv::ContentType_Nack);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800419 BOOST_CHECK_EQUAL(ControlResponse(face.sentData[0].getContent().blockFromValue()).getCode(), 400);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800420 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 -0700421}
422
Junxiao Shid97c9532017-04-27 16:17:04 +0000423BOOST_AUTO_TEST_CASE(NotificationStream)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700424{
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500425 const Block block({0x82, 0x01, 0x02});
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700426 auto post = dispatcher.addNotificationStream("test");
427
428 post(block);
Davide Pesavento0f830802018-01-16 23:58:58 -0500429 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800430 BOOST_CHECK_EQUAL(face.sentData.size(), 0);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700431
432 dispatcher.addTopPrefix("/root");
Davide Pesavento0f830802018-01-16 23:58:58 -0500433 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800434 face.sentData.clear();
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700435
436 post(block);
Davide Pesavento0f830802018-01-16 23:58:58 -0500437 advanceClocks(1_ms);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800438 BOOST_CHECK_EQUAL(face.sentData.size(), 1);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800439 BOOST_CHECK_EQUAL(storage.size(), 1);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700440
441 post(block);
442 post(block);
443 post(block);
Davide Pesavento0f830802018-01-16 23:58:58 -0500444 advanceClocks(1_ms, 10);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700445
Junxiao Shi72c0c642018-04-20 15:41:09 +0000446 BOOST_REQUIRE_EQUAL(face.sentData.size(), 4);
Eric Newberryc25e4632021-02-11 10:48:11 -0800447 BOOST_CHECK_EQUAL(face.sentData[0].getName(), "/root/test/seq=0");
448 BOOST_CHECK_EQUAL(face.sentData[1].getName(), "/root/test/seq=1");
449 BOOST_CHECK_EQUAL(face.sentData[2].getName(), "/root/test/seq=2");
450 BOOST_CHECK_EQUAL(face.sentData[3].getName(), "/root/test/seq=3");
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700451
Junxiao Shi72c0c642018-04-20 15:41:09 +0000452 BOOST_CHECK_EQUAL(face.sentData[0].getContent().blockFromValue(), block);
453 BOOST_CHECK_EQUAL(face.sentData[1].getContent().blockFromValue(), block);
454 BOOST_CHECK_EQUAL(face.sentData[2].getContent().blockFromValue(), block);
455 BOOST_CHECK_EQUAL(face.sentData[3].getContent().blockFromValue(), block);
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800456
457 // each version of notification will be sent to both places
458 std::vector<Data> dataInStorage;
459 std::copy(storage.begin(), storage.end(), std::back_inserter(dataInStorage));
Junxiao Shi72c0c642018-04-20 15:41:09 +0000460 BOOST_REQUIRE_EQUAL(dataInStorage.size(), 4);
Eric Newberryc25e4632021-02-11 10:48:11 -0800461 BOOST_CHECK_EQUAL(dataInStorage[0].getName(), "/root/test/seq=0");
462 BOOST_CHECK_EQUAL(dataInStorage[1].getName(), "/root/test/seq=1");
463 BOOST_CHECK_EQUAL(dataInStorage[2].getName(), "/root/test/seq=2");
464 BOOST_CHECK_EQUAL(dataInStorage[3].getName(), "/root/test/seq=3");
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800465
Junxiao Shi72c0c642018-04-20 15:41:09 +0000466 BOOST_CHECK_EQUAL(dataInStorage[0].getContent().blockFromValue(), block);
467 BOOST_CHECK_EQUAL(dataInStorage[1].getContent().blockFromValue(), block);
468 BOOST_CHECK_EQUAL(dataInStorage[2].getContent().blockFromValue(), block);
469 BOOST_CHECK_EQUAL(dataInStorage[3].getContent().blockFromValue(), block);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700470}
471
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800472BOOST_AUTO_TEST_SUITE_END() // TestDispatcher
473BOOST_AUTO_TEST_SUITE_END() // Mgmt
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700474
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400475} // namespace ndn::tests