blob: e3b7aa9b16e7489bb7ae4b30d69449f186eb191e [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/*
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +00003 * Copyright (c) 2014-2019 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 Pesavento7e780642018-11-24 15:51:34 -050031#include "tests/boost-test.hpp"
32#include "tests/make-interest-data.hpp"
33#include "tests/unit/identity-management-time-fixture.hpp"
34#include "tests/unit/util/simple-notification.hpp"
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070035
36namespace ndn {
Junxiao Shia60d9362014-11-12 09:38:21 -070037namespace util {
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070038namespace tests {
39
Teng Liang93adaff2016-07-30 15:57:12 -070040using namespace ndn::tests;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070041
Alexander Afanasyev80782e02017-01-04 13:16:54 -080042class NotificationSubscriberFixture : public IdentityManagementTimeFixture
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070043{
44public:
Teng Liang93adaff2016-07-30 15:57:12 -070045 NotificationSubscriberFixture()
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070046 : streamPrefix("ndn:/NotificationSubscriberTest")
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -070047 , subscriberFace(io, m_keyChain)
Davide Pesavento0f830802018-01-16 23:58:58 -050048 , subscriber(subscriberFace, streamPrefix, 1_s)
Teng Liang93adaff2016-07-30 15:57:12 -070049 , nextSendNotificationNo(0)
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070050 {
51 }
52
Teng Liang93adaff2016-07-30 15:57:12 -070053 /** \brief deliver one notification to subscriber
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070054 */
55 void
56 deliverNotification(const std::string& msg)
57 {
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070058 SimpleNotification notification(msg);
Alexander Afanasyev370d2602014-08-20 10:21:34 -050059
Teng Liang93adaff2016-07-30 15:57:12 -070060 Name dataName = streamPrefix;
61 dataName.appendSequenceNumber(nextSendNotificationNo);
62 Data data(dataName);
63 data.setContent(notification.wireEncode());
Davide Pesavento0f830802018-01-16 23:58:58 -050064 data.setFreshnessPeriod(1_s);
Teng Liang93adaff2016-07-30 15:57:12 -070065 m_keyChain.sign(data);
Alexander Afanasyev370d2602014-08-20 10:21:34 -050066
Junxiao Shi946a51c2018-11-24 00:25:57 +000067 lastDeliveredSeqNum = nextSendNotificationNo;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070068 lastNotification.setMessage("");
Teng Liang93adaff2016-07-30 15:57:12 -070069 ++nextSendNotificationNo;
70 subscriberFace.receive(data);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070071 }
72
Teng Liangf8bf1b02016-07-17 11:54:19 -070073 /** \brief deliver a Nack to subscriber
74 */
75 void
76 deliverNack(const Interest& interest, const lp::NackReason& reason)
77 {
78 lp::Nack nack = makeNack(interest, reason);
79 subscriberFace.receive(nack);
80 }
81
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070082 void
83 afterNotification(const SimpleNotification& notification)
84 {
85 lastNotification = notification;
86 }
87
88 void
Teng Liangf8bf1b02016-07-17 11:54:19 -070089 afterNack(const lp::Nack& nack)
90 {
91 lastNack = nack;
92 }
93
94 void
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070095 afterTimeout()
96 {
97 hasTimeout = true;
98 }
99
100 void
101 afterDecodeError(const Data& data)
102 {
103 lastDecodeErrorData = data;
104 }
105
Teng Liang93adaff2016-07-30 15:57:12 -0700106 void
107 connectHandlers()
108 {
109 notificationConn = subscriber.onNotification.connect(
110 bind(&NotificationSubscriberFixture::afterNotification, this, _1));
Teng Liangf8bf1b02016-07-17 11:54:19 -0700111 nackConn = subscriber.onNack.connect(
112 bind(&NotificationSubscriberFixture::afterNack, this, _1));
Teng Liang93adaff2016-07-30 15:57:12 -0700113 subscriber.onTimeout.connect(
114 bind(&NotificationSubscriberFixture::afterTimeout, this));
115 subscriber.onDecodeError.connect(
116 bind(&NotificationSubscriberFixture::afterDecodeError, this, _1));
117 }
118
119 void
120 disconnectHandlers()
121 {
122 notificationConn.disconnect();
Teng Liangf8bf1b02016-07-17 11:54:19 -0700123 nackConn.disconnect();
Teng Liang93adaff2016-07-30 15:57:12 -0700124 }
125
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700126 /** \return true if subscriberFace has an initial request (first sent Interest)
127 */
128 bool
129 hasInitialRequest() const
130 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800131 if (subscriberFace.sentInterests.empty())
Teng Liang93adaff2016-07-30 15:57:12 -0700132 return false;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700133
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800134 const Interest& interest = subscriberFace.sentInterests[0];
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700135 return interest.getName() == streamPrefix &&
Junxiao Shi946a51c2018-11-24 00:25:57 +0000136 interest.getCanBePrefix() &&
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700137 interest.getMustBeFresh() &&
138 interest.getInterestLifetime() == subscriber.getInterestLifetime();
139 }
140
141 /** \return sequence number of the continuation request sent from subscriberFace
142 * or 0 if there's no such request as sole sent Interest
143 */
144 uint64_t
Junxiao Shi946a51c2018-11-24 00:25:57 +0000145 getRequestSeqNum() const
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700146 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800147 if (subscriberFace.sentInterests.size() != 1)
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700148 return 0;
149
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800150 const Interest& interest = subscriberFace.sentInterests[0];
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700151 const Name& name = interest.getName();
152 if (streamPrefix.isPrefixOf(name) &&
153 name.size() == streamPrefix.size() + 1 &&
154 interest.getInterestLifetime() == subscriber.getInterestLifetime())
155 return name[-1].toSequenceNumber();
156 else
157 return 0;
158 }
159
160protected:
161 Name streamPrefix;
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800162 DummyClientFace subscriberFace;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700163 util::NotificationSubscriber<SimpleNotification> subscriber;
Junxiao Shi728873f2015-01-20 16:01:26 -0700164 util::signal::Connection notificationConn;
Teng Liangf8bf1b02016-07-17 11:54:19 -0700165 util::signal::Connection nackConn;
Teng Liang93adaff2016-07-30 15:57:12 -0700166 uint64_t nextSendNotificationNo;
Junxiao Shi946a51c2018-11-24 00:25:57 +0000167 uint64_t lastDeliveredSeqNum;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700168 SimpleNotification lastNotification;
Teng Liangf8bf1b02016-07-17 11:54:19 -0700169 lp::Nack lastNack;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700170 bool hasTimeout;
171 Data lastDecodeErrorData;
172};
173
Teng Liang93adaff2016-07-30 15:57:12 -0700174BOOST_AUTO_TEST_SUITE(Util)
175BOOST_FIXTURE_TEST_SUITE(TestNotificationSubscriber, NotificationSubscriberFixture)
176
177BOOST_AUTO_TEST_CASE(StartStop)
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700178{
179 BOOST_REQUIRE_EQUAL(subscriber.isRunning(), false);
180
181 // has no effect because onNotification has no handler
182 subscriber.start();
183 BOOST_REQUIRE_EQUAL(subscriber.isRunning(), false);
184
Teng Liang93adaff2016-07-30 15:57:12 -0700185 this->connectHandlers();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700186 subscriber.start();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700187 BOOST_REQUIRE_EQUAL(subscriber.isRunning(), true);
Davide Pesavento0f830802018-01-16 23:58:58 -0500188 advanceClocks(1_ms);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700189 BOOST_CHECK(this->hasInitialRequest());
190
Teng Liang93adaff2016-07-30 15:57:12 -0700191 subscriberFace.sentInterests.clear();
192 this->disconnectHandlers();
193 this->deliverNotification("n1");
194 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 0);
195}
196
197BOOST_AUTO_TEST_CASE(Notifications)
198{
199 this->connectHandlers();
200 subscriber.start();
Davide Pesavento0f830802018-01-16 23:58:58 -0500201 advanceClocks(1_ms);
Teng Liang93adaff2016-07-30 15:57:12 -0700202
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700203 // respond to initial request
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800204 subscriberFace.sentInterests.clear();
Teng Liang93adaff2016-07-30 15:57:12 -0700205 this->deliverNotification("n1");
Davide Pesavento0f830802018-01-16 23:58:58 -0500206 advanceClocks(1_ms);
Teng Liang93adaff2016-07-30 15:57:12 -0700207 BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n1");
Junxiao Shi946a51c2018-11-24 00:25:57 +0000208 BOOST_CHECK_EQUAL(this->getRequestSeqNum(), lastDeliveredSeqNum + 1);
Teng Liang93adaff2016-07-30 15:57:12 -0700209
210 // respond to continuation request
211 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700212 this->deliverNotification("n2");
Davide Pesavento0f830802018-01-16 23:58:58 -0500213 advanceClocks(1_ms);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700214 BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n2");
Junxiao Shi946a51c2018-11-24 00:25:57 +0000215 BOOST_CHECK_EQUAL(this->getRequestSeqNum(), lastDeliveredSeqNum + 1);
Teng Liang93adaff2016-07-30 15:57:12 -0700216}
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700217
Teng Liangf8bf1b02016-07-17 11:54:19 -0700218BOOST_AUTO_TEST_CASE(Nack)
219{
220 this->connectHandlers();
221 subscriber.start();
Davide Pesavento0f830802018-01-16 23:58:58 -0500222 advanceClocks(1_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700223
224 // send the first Nack to initial request
225 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 1);
226 Interest interest = subscriberFace.sentInterests[0];
227 subscriberFace.sentInterests.clear();
228 this->deliverNack(interest, lp::NackReason::CONGESTION);
Davide Pesavento0f830802018-01-16 23:58:58 -0500229 advanceClocks(1_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700230 BOOST_CHECK_EQUAL(lastNack.getReason(), lp::NackReason::CONGESTION);
231 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), false);
Davide Pesavento0f830802018-01-16 23:58:58 -0500232 advanceClocks(300_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700233 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), true);
234
235 // send the second Nack to initial request
236 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 1);
237 interest = subscriberFace.sentInterests[0];
238 subscriberFace.sentInterests.clear();
239 this->deliverNack(interest, lp::NackReason::CONGESTION);
Davide Pesavento0f830802018-01-16 23:58:58 -0500240 advanceClocks(301_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700241 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), false);
Davide Pesavento0f830802018-01-16 23:58:58 -0500242 advanceClocks(200_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700243 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), true);
244
245 // send a notification to initial request
246 subscriberFace.sentInterests.clear();
247 this->deliverNotification("n1");
Davide Pesavento0f830802018-01-16 23:58:58 -0500248 advanceClocks(1_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700249
250 // send a Nack to subsequent request
251 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 1);
252 interest = subscriberFace.sentInterests[0];
253 subscriberFace.sentInterests.clear();
254 this->deliverNack(interest, lp::NackReason::CONGESTION);
Davide Pesavento0f830802018-01-16 23:58:58 -0500255 advanceClocks(1_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700256 BOOST_CHECK_EQUAL(lastNack.getReason(), lp::NackReason::CONGESTION);
257 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), false);
Davide Pesavento0f830802018-01-16 23:58:58 -0500258 advanceClocks(300_ms);
Teng Liangf8bf1b02016-07-17 11:54:19 -0700259 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), true);
260}
261
Teng Liang93adaff2016-07-30 15:57:12 -0700262BOOST_AUTO_TEST_CASE(Timeout)
263{
264 this->connectHandlers();
265 subscriber.start();
Davide Pesavento0f830802018-01-16 23:58:58 -0500266 advanceClocks(1_ms);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700267
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800268 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700269 lastNotification.setMessage("");
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800270 advanceClocks(subscriber.getInterestLifetime(), 2);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700271 BOOST_CHECK(lastNotification.getMessage().empty());
272 BOOST_CHECK_EQUAL(hasTimeout, true);
273 BOOST_CHECK(this->hasInitialRequest());
274
Teng Liang93adaff2016-07-30 15:57:12 -0700275 subscriberFace.sentInterests.clear();
276 this->deliverNotification("n1");
Davide Pesavento0f830802018-01-16 23:58:58 -0500277 advanceClocks(1_ms);
Teng Liang93adaff2016-07-30 15:57:12 -0700278 BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n1");
279}
280
281BOOST_AUTO_TEST_CASE(SequenceError)
282{
283 this->connectHandlers();
284 subscriber.start();
Davide Pesavento0f830802018-01-16 23:58:58 -0500285 advanceClocks(1_ms);
Teng Liang93adaff2016-07-30 15:57:12 -0700286
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700287 Name wrongName = streamPrefix;
288 wrongName.append("%07%07");
289 Data wrongData(wrongName);
Junxiao Shi2ad2fbe2019-05-24 03:11:05 +0000290 wrongData.setFreshnessPeriod(1_s);
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -0700291 m_keyChain.sign(wrongData);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800292 subscriberFace.receive(wrongData);
293 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700294 lastNotification.setMessage("");
Davide Pesavento0f830802018-01-16 23:58:58 -0500295 advanceClocks(1_ms);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700296 BOOST_CHECK(lastNotification.getMessage().empty());
297 BOOST_CHECK_EQUAL(lastDecodeErrorData.getName(), wrongName);
298 BOOST_CHECK(this->hasInitialRequest());
Teng Liang93adaff2016-07-30 15:57:12 -0700299}
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700300
Teng Liang93adaff2016-07-30 15:57:12 -0700301BOOST_AUTO_TEST_CASE(PayloadError)
302{
303 this->connectHandlers();
304 subscriber.start();
Davide Pesavento0f830802018-01-16 23:58:58 -0500305 advanceClocks(1_ms);
Teng Liang93adaff2016-07-30 15:57:12 -0700306
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800307 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700308 lastNotification.setMessage("");
309 this->deliverNotification("\x07n4");
Davide Pesavento0f830802018-01-16 23:58:58 -0500310 advanceClocks(1_ms);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700311 BOOST_CHECK(lastNotification.getMessage().empty());
312 BOOST_CHECK(this->hasInitialRequest());
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700313}
314
Teng Liang93adaff2016-07-30 15:57:12 -0700315BOOST_AUTO_TEST_SUITE_END() // TestNotificationSubscriber
316BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700317
318} // namespace tests
Junxiao Shia60d9362014-11-12 09:38:21 -0700319} // namespace util
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700320} // namespace ndn