blob: 896f632439c1973c1e019df90ef3f423ecd2a424 [file] [log] [blame]
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi2bea5c42017-08-14 20:10:32 +00002/*
Davide Pesaventoc860bd12022-10-04 03:23:43 -04003 * Copyright (c) 2014-2022 Regents of the University of California,
Spyridon Mastorakis429634f2015-02-19 17:35:33 -08004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070010 *
11 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
12 *
13 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
14 * terms of the GNU Lesser General Public License as published by the Free Software
15 * Foundation, either version 3 of the License, or (at your option) any later version.
16 *
17 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
20 *
21 * You should have received copies of the GNU General Public License and GNU Lesser
22 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
23 * <http://www.gnu.org/licenses/>.
24 *
25 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
26 */
27
Davide Pesavento7e780642018-11-24 15:51:34 -050028#include "ndn-cxx/util/notification-subscriber.hpp"
29#include "ndn-cxx/util/dummy-client-face.hpp"
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070030
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050031#include "tests/test-common.hpp"
32#include "tests/unit/io-key-chain-fixture.hpp"
Davide Pesavento7e780642018-11-24 15:51:34 -050033#include "tests/unit/util/simple-notification.hpp"
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070034
35namespace ndn {
Junxiao Shia60d9362014-11-12 09:38:21 -070036namespace util {
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070037namespace tests {
38
Teng Liang93adaff2016-07-30 15:57:12 -070039using namespace ndn::tests;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070040
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050041class NotificationSubscriberFixture : public IoKeyChainFixture
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070042{
43public:
Teng Liang93adaff2016-07-30 15:57:12 -070044 NotificationSubscriberFixture()
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050045 : streamPrefix("/NotificationSubscriberTest")
46 , subscriberFace(m_io, m_keyChain)
Davide Pesavento0f830802018-01-16 23:58:58 -050047 , subscriber(subscriberFace, streamPrefix, 1_s)
Teng Liang93adaff2016-07-30 15:57:12 -070048 , nextSendNotificationNo(0)
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070049 {
50 }
51
Davide Pesaventoc860bd12022-10-04 03:23:43 -040052 /** \brief Deliver one notification to subscriber.
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070053 */
54 void
55 deliverNotification(const std::string& msg)
56 {
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070057 SimpleNotification notification(msg);
Alexander Afanasyev370d2602014-08-20 10:21:34 -050058
Teng Liang93adaff2016-07-30 15:57:12 -070059 Name dataName = streamPrefix;
60 dataName.appendSequenceNumber(nextSendNotificationNo);
61 Data data(dataName);
62 data.setContent(notification.wireEncode());
Davide Pesavento0f830802018-01-16 23:58:58 -050063 data.setFreshnessPeriod(1_s);
Teng Liang93adaff2016-07-30 15:57:12 -070064 m_keyChain.sign(data);
Alexander Afanasyev370d2602014-08-20 10:21:34 -050065
Junxiao Shi946a51c2018-11-24 00:25:57 +000066 lastDeliveredSeqNum = nextSendNotificationNo;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070067 lastNotification.setMessage("");
Teng Liang93adaff2016-07-30 15:57:12 -070068 ++nextSendNotificationNo;
69 subscriberFace.receive(data);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070070 }
71
Davide Pesaventoc860bd12022-10-04 03:23:43 -040072 /** \brief Deliver a Nack to subscriber.
Teng Liangf8bf1b02016-07-17 11:54:19 -070073 */
74 void
75 deliverNack(const Interest& interest, const lp::NackReason& reason)
76 {
Davide Pesavento2e481fc2021-07-02 18:20:03 -040077 subscriberFace.receive(makeNack(interest, reason));
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070078 }
79
Teng Liang93adaff2016-07-30 15:57:12 -070080 void
81 connectHandlers()
82 {
Davide Pesavento2e481fc2021-07-02 18:20:03 -040083 notificationConn = subscriber.onNotification.connect([this] (const auto& n) { lastNotification = n; });
84 nackConn = subscriber.onNack.connect([this] (const auto& nack) { lastNack = nack; });
85 subscriber.onTimeout.connect([this] { hasTimeout = true; });
86 subscriber.onDecodeError.connect([this] (const auto& data) { lastDecodeErrorData = data; });
Teng Liang93adaff2016-07-30 15:57:12 -070087 }
88
89 void
90 disconnectHandlers()
91 {
92 notificationConn.disconnect();
Teng Liangf8bf1b02016-07-17 11:54:19 -070093 nackConn.disconnect();
Teng Liang93adaff2016-07-30 15:57:12 -070094 }
95
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070096 /** \return true if subscriberFace has an initial request (first sent Interest)
97 */
98 bool
99 hasInitialRequest() const
100 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800101 if (subscriberFace.sentInterests.empty())
Teng Liang93adaff2016-07-30 15:57:12 -0700102 return false;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700103
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800104 const Interest& interest = subscriberFace.sentInterests[0];
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700105 return interest.getName() == streamPrefix &&
Junxiao Shi946a51c2018-11-24 00:25:57 +0000106 interest.getCanBePrefix() &&
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700107 interest.getMustBeFresh() &&
108 interest.getInterestLifetime() == subscriber.getInterestLifetime();
109 }
110
111 /** \return sequence number of the continuation request sent from subscriberFace
112 * or 0 if there's no such request as sole sent Interest
113 */
114 uint64_t
Junxiao Shi946a51c2018-11-24 00:25:57 +0000115 getRequestSeqNum() const
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700116 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800117 if (subscriberFace.sentInterests.size() != 1)
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700118 return 0;
119
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800120 const Interest& interest = subscriberFace.sentInterests[0];
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700121 const Name& name = interest.getName();
122 if (streamPrefix.isPrefixOf(name) &&
123 name.size() == streamPrefix.size() + 1 &&
124 interest.getInterestLifetime() == subscriber.getInterestLifetime())
125 return name[-1].toSequenceNumber();
126 else
127 return 0;
128 }
129
130protected:
131 Name streamPrefix;
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800132 DummyClientFace subscriberFace;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700133 util::NotificationSubscriber<SimpleNotification> subscriber;
Junxiao Shi728873f2015-01-20 16:01:26 -0700134 util::signal::Connection notificationConn;
Teng Liangf8bf1b02016-07-17 11:54:19 -0700135 util::signal::Connection nackConn;
Teng Liang93adaff2016-07-30 15:57:12 -0700136 uint64_t nextSendNotificationNo;
Junxiao Shi946a51c2018-11-24 00:25:57 +0000137 uint64_t lastDeliveredSeqNum;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700138 SimpleNotification lastNotification;
Teng Liangf8bf1b02016-07-17 11:54:19 -0700139 lp::Nack lastNack;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700140 bool hasTimeout;
141 Data lastDecodeErrorData;
142};
143
Teng Liang93adaff2016-07-30 15:57:12 -0700144BOOST_AUTO_TEST_SUITE(Util)
145BOOST_FIXTURE_TEST_SUITE(TestNotificationSubscriber, NotificationSubscriberFixture)
146
147BOOST_AUTO_TEST_CASE(StartStop)
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700148{
149 BOOST_REQUIRE_EQUAL(subscriber.isRunning(), false);
150
151 // has no effect because onNotification has no handler
152 subscriber.start();
153 BOOST_REQUIRE_EQUAL(subscriber.isRunning(), false);
154
Teng Liang93adaff2016-07-30 15:57:12 -0700155 this->connectHandlers();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700156 subscriber.start();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700157 BOOST_REQUIRE_EQUAL(subscriber.isRunning(), true);
Davide Pesavento0f830802018-01-16 23:58:58 -0500158 advanceClocks(1_ms);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700159 BOOST_CHECK(this->hasInitialRequest());
160
Teng Liang93adaff2016-07-30 15:57:12 -0700161 subscriberFace.sentInterests.clear();
162 this->disconnectHandlers();
163 this->deliverNotification("n1");
164 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 0);
165}
166
167BOOST_AUTO_TEST_CASE(Notifications)
168{
169 this->connectHandlers();
170 subscriber.start();
Davide Pesavento0f830802018-01-16 23:58:58 -0500171 advanceClocks(1_ms);
Teng Liang93adaff2016-07-30 15:57:12 -0700172
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700173 // respond to initial request
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800174 subscriberFace.sentInterests.clear();
Teng Liang93adaff2016-07-30 15:57:12 -0700175 this->deliverNotification("n1");
Davide Pesavento0f830802018-01-16 23:58:58 -0500176 advanceClocks(1_ms);
Teng Liang93adaff2016-07-30 15:57:12 -0700177 BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n1");
Junxiao Shi946a51c2018-11-24 00:25:57 +0000178 BOOST_CHECK_EQUAL(this->getRequestSeqNum(), lastDeliveredSeqNum + 1);
Teng Liang93adaff2016-07-30 15:57:12 -0700179
180 // respond to continuation request
181 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700182 this->deliverNotification("n2");
Davide Pesavento0f830802018-01-16 23:58:58 -0500183 advanceClocks(1_ms);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700184 BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n2");
Junxiao Shi946a51c2018-11-24 00:25:57 +0000185 BOOST_CHECK_EQUAL(this->getRequestSeqNum(), lastDeliveredSeqNum + 1);
Teng Liang93adaff2016-07-30 15:57:12 -0700186}
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700187
Teng Liangf8bf1b02016-07-17 11:54:19 -0700188BOOST_AUTO_TEST_CASE(Nack)
189{
190 this->connectHandlers();
191 subscriber.start();
Davide Pesavento0f830802018-01-16 23:58:58 -0500192 advanceClocks(1_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700193
194 // send the first Nack to initial request
195 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 1);
196 Interest interest = subscriberFace.sentInterests[0];
197 subscriberFace.sentInterests.clear();
198 this->deliverNack(interest, lp::NackReason::CONGESTION);
Davide Pesavento0f830802018-01-16 23:58:58 -0500199 advanceClocks(1_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700200 BOOST_CHECK_EQUAL(lastNack.getReason(), lp::NackReason::CONGESTION);
201 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), false);
Davide Pesavento0f830802018-01-16 23:58:58 -0500202 advanceClocks(300_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700203 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), true);
204
205 // send the second Nack to initial request
206 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 1);
207 interest = subscriberFace.sentInterests[0];
208 subscriberFace.sentInterests.clear();
209 this->deliverNack(interest, lp::NackReason::CONGESTION);
Davide Pesavento0f830802018-01-16 23:58:58 -0500210 advanceClocks(301_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700211 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), false);
Davide Pesavento0f830802018-01-16 23:58:58 -0500212 advanceClocks(200_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700213 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), true);
214
215 // send a notification to initial request
216 subscriberFace.sentInterests.clear();
217 this->deliverNotification("n1");
Davide Pesavento0f830802018-01-16 23:58:58 -0500218 advanceClocks(1_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700219
220 // send a Nack to subsequent request
221 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 1);
222 interest = subscriberFace.sentInterests[0];
223 subscriberFace.sentInterests.clear();
224 this->deliverNack(interest, lp::NackReason::CONGESTION);
Davide Pesavento0f830802018-01-16 23:58:58 -0500225 advanceClocks(1_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700226 BOOST_CHECK_EQUAL(lastNack.getReason(), lp::NackReason::CONGESTION);
227 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), false);
Davide Pesavento0f830802018-01-16 23:58:58 -0500228 advanceClocks(300_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700229 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), true);
230}
231
Teng Liang93adaff2016-07-30 15:57:12 -0700232BOOST_AUTO_TEST_CASE(Timeout)
233{
234 this->connectHandlers();
235 subscriber.start();
Davide Pesavento0f830802018-01-16 23:58:58 -0500236 advanceClocks(1_ms);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700237
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800238 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700239 lastNotification.setMessage("");
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800240 advanceClocks(subscriber.getInterestLifetime(), 2);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700241 BOOST_CHECK(lastNotification.getMessage().empty());
242 BOOST_CHECK_EQUAL(hasTimeout, true);
243 BOOST_CHECK(this->hasInitialRequest());
244
Teng Liang93adaff2016-07-30 15:57:12 -0700245 subscriberFace.sentInterests.clear();
246 this->deliverNotification("n1");
Davide Pesavento0f830802018-01-16 23:58:58 -0500247 advanceClocks(1_ms);
Teng Liang93adaff2016-07-30 15:57:12 -0700248 BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n1");
249}
250
251BOOST_AUTO_TEST_CASE(SequenceError)
252{
253 this->connectHandlers();
254 subscriber.start();
Davide Pesavento0f830802018-01-16 23:58:58 -0500255 advanceClocks(1_ms);
Teng Liang93adaff2016-07-30 15:57:12 -0700256
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700257 Name wrongName = streamPrefix;
258 wrongName.append("%07%07");
259 Data wrongData(wrongName);
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000260 wrongData.setFreshnessPeriod(1_s);
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -0700261 m_keyChain.sign(wrongData);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800262 subscriberFace.receive(wrongData);
263 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700264 lastNotification.setMessage("");
Davide Pesavento0f830802018-01-16 23:58:58 -0500265 advanceClocks(1_ms);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700266 BOOST_CHECK(lastNotification.getMessage().empty());
267 BOOST_CHECK_EQUAL(lastDecodeErrorData.getName(), wrongName);
268 BOOST_CHECK(this->hasInitialRequest());
Teng Liang93adaff2016-07-30 15:57:12 -0700269}
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700270
Teng Liang93adaff2016-07-30 15:57:12 -0700271BOOST_AUTO_TEST_CASE(PayloadError)
272{
273 this->connectHandlers();
274 subscriber.start();
Davide Pesavento0f830802018-01-16 23:58:58 -0500275 advanceClocks(1_ms);
Teng Liang93adaff2016-07-30 15:57:12 -0700276
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800277 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700278 lastNotification.setMessage("");
279 this->deliverNotification("\x07n4");
Davide Pesavento0f830802018-01-16 23:58:58 -0500280 advanceClocks(1_ms);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700281 BOOST_CHECK(lastNotification.getMessage().empty());
282 BOOST_CHECK(this->hasInitialRequest());
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700283}
284
Teng Liang93adaff2016-07-30 15:57:12 -0700285BOOST_AUTO_TEST_SUITE_END() // TestNotificationSubscriber
286BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700287
288} // namespace tests
Junxiao Shia60d9362014-11-12 09:38:21 -0700289} // namespace util
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700290} // namespace ndn